Prechádzať zdrojové kódy

Convert to kt, Use M3 components

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 1 rok pred
rodič
commit
e7f5511023

+ 412 - 405
app/src/main/java/com/owncloud/android/ui/dialog/SetupEncryptionDialogFragment.kt

@@ -20,532 +20,539 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-package com.owncloud.android.ui.dialog;
-
-import android.accounts.AccountManager;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.Button;
-
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-import com.nextcloud.client.account.User;
-import com.nextcloud.client.di.Injectable;
-import com.owncloud.android.R;
-import com.owncloud.android.databinding.SetupEncryptionDialogBinding;
-import com.owncloud.android.datamodel.ArbitraryDataProvider;
-import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
-import com.owncloud.android.lib.common.accounts.AccountUtils;
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.users.DeletePublicKeyOperation;
-import com.owncloud.android.lib.resources.users.GetPrivateKeyOperation;
-import com.owncloud.android.lib.resources.users.GetPublicKeyOperation;
-import com.owncloud.android.lib.resources.users.SendCSROperation;
-import com.owncloud.android.lib.resources.users.StorePrivateKeyOperation;
-import com.owncloud.android.utils.CsrHelper;
-import com.owncloud.android.utils.EncryptionUtils;
-import com.owncloud.android.utils.theme.ViewThemeUtils;
-
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Locale;
-
-import javax.inject.Inject;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.DialogFragment;
-import androidx.fragment.app.Fragment;
-
-import static com.owncloud.android.utils.EncryptionUtils.MNEMONIC;
-import static com.owncloud.android.utils.EncryptionUtils.decodeStringToBase64Bytes;
-import static com.owncloud.android.utils.EncryptionUtils.decryptStringAsymmetric;
-import static com.owncloud.android.utils.EncryptionUtils.encodeBytesToBase64String;
-import static com.owncloud.android.utils.EncryptionUtils.generateKey;
+package com.owncloud.android.ui.dialog
+
+import android.accounts.AccountManager
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.content.Context
+import android.content.DialogInterface
+import android.content.Intent
+import android.os.AsyncTask
+import android.os.Build
+import android.os.Bundle
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.button.MaterialButton
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.nextcloud.client.account.User
+import com.nextcloud.client.di.Injectable
+import com.owncloud.android.R
+import com.owncloud.android.databinding.SetupEncryptionDialogBinding
+import com.owncloud.android.datamodel.ArbitraryDataProvider
+import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
+import com.owncloud.android.lib.common.accounts.AccountUtils
+import com.owncloud.android.lib.common.utils.Log_OC
+import com.owncloud.android.lib.resources.users.DeletePublicKeyOperation
+import com.owncloud.android.lib.resources.users.GetPrivateKeyOperation
+import com.owncloud.android.lib.resources.users.GetPublicKeyOperation
+import com.owncloud.android.lib.resources.users.SendCSROperation
+import com.owncloud.android.lib.resources.users.StorePrivateKeyOperation
+import com.owncloud.android.utils.CsrHelper
+import com.owncloud.android.utils.EncryptionUtils
+import com.owncloud.android.utils.theme.ViewThemeUtils
+import java.io.IOException
+import java.lang.ref.WeakReference
+import java.util.Arrays
+import javax.inject.Inject
 
 /*
  *  Dialog to setup encryption
  */
-public class SetupEncryptionDialogFragment extends DialogFragment implements Injectable {
-
-    public static final String SUCCESS = "SUCCESS";
-    public static final int SETUP_ENCRYPTION_RESULT_CODE = 101;
-    public static final int SETUP_ENCRYPTION_REQUEST_CODE = 100;
-    public static final String SETUP_ENCRYPTION_DIALOG_TAG = "SETUP_ENCRYPTION_DIALOG_TAG";
-    public static final String ARG_POSITION = "ARG_POSITION";
-
-    public static final String RESULT_REQUEST_KEY = "RESULT_REQUEST";
-    public static final String RESULT_KEY_CANCELLED = "IS_CANCELLED";
-
-    private static final String ARG_USER = "ARG_USER";
-    private static final String TAG = SetupEncryptionDialogFragment.class.getSimpleName();
-
-    private static final String KEY_CREATED = "KEY_CREATED";
-    private static final String KEY_EXISTING_USED = "KEY_EXISTING_USED";
-    private static final String KEY_FAILED = "KEY_FAILED";
-    private static final String KEY_GENERATE = "KEY_GENERATE";
-
-    @Inject ViewThemeUtils viewThemeUtils;
-
-    private User user;
-    private ArbitraryDataProvider arbitraryDataProvider;
-    private Button positiveButton;
-    private Button neutralButton;
-    private DownloadKeysAsyncTask task;
-    private String keyResult;
-    private ArrayList<String> keyWords;
-    private SetupEncryptionDialogBinding binding;
-
-    /**
-     * Public factory method to create new SetupEncryptionDialogFragment instance
-     *
-     * @return Dialog ready to show.
-     */
-    public static SetupEncryptionDialogFragment newInstance(User user, int position) {
-        SetupEncryptionDialogFragment fragment = new SetupEncryptionDialogFragment();
-        Bundle args = new Bundle();
-        args.putParcelable(ARG_USER, user);
-        args.putInt(ARG_POSITION, position);
-        fragment.setArguments(args);
-        return fragment;
-    }
+class SetupEncryptionDialogFragment : DialogFragment(), Injectable {
+
+    @JvmField
+    @Inject
+    var viewThemeUtils: ViewThemeUtils? = null
+
+    private var user: User? = null
+    private var arbitraryDataProvider: ArbitraryDataProvider? = null
+    private var positiveButton: MaterialButton? = null
+    private var negativeButton: MaterialButton? = null
+    private var task: DownloadKeysAsyncTask? = null
+    private var keyResult: String? = null
+    private var keyWords: ArrayList<String>? = null
+
+    private lateinit var binding: SetupEncryptionDialogBinding
+
+    override fun onStart() {
+        super.onStart()
 
-    @Override
-    public void onStart() {
-        super.onStart();
+        setupAlertDialog()
+        executeTask()
+    }
 
-        AlertDialog alertDialog = (AlertDialog) getDialog();
+    private fun setupAlertDialog() {
+        val alertDialog = dialog as AlertDialog?
 
         if (alertDialog != null) {
-            positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
-            neutralButton = alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL);
-            viewThemeUtils.platform.colorTextButtons(positiveButton, neutralButton);
+            positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as MaterialButton?
+            negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as MaterialButton?
+
+            if (positiveButton != null) {
+                viewThemeUtils?.material?.colorMaterialButtonPrimaryTonal(positiveButton!!)
+            }
+
+            if (negativeButton != null) {
+                viewThemeUtils?.material?.colorMaterialButtonPrimaryBorderless(negativeButton!!)
+            }
         }
+    }
 
-        task = new DownloadKeysAsyncTask(requireContext());
-        task.execute();
+    private fun executeTask() {
+        task = DownloadKeysAsyncTask(requireContext())
+        task?.execute()
     }
 
-    @NonNull
-    @Override
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
-        if (getArguments() == null) {
-            throw new IllegalStateException("Arguments may not be null");
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        checkNotNull(arguments) { "Arguments may not be null" }
+
+        user = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            requireArguments().getParcelable(ARG_USER, User::class.java)
+        } else {
+            @Suppress("DEPRECATION")
+            requireArguments().getParcelable(ARG_USER)
         }
-        user = getArguments().getParcelable(ARG_USER);
 
         if (savedInstanceState != null) {
-            keyWords = savedInstanceState.getStringArrayList(MNEMONIC);
+            keyWords = savedInstanceState.getStringArrayList(EncryptionUtils.MNEMONIC)
         }
 
-        arbitraryDataProvider = new ArbitraryDataProviderImpl(getContext());
+        arbitraryDataProvider = ArbitraryDataProviderImpl(context)
 
         // Inflate the layout for the dialog
-        LayoutInflater inflater = requireActivity().getLayoutInflater();
-        binding = SetupEncryptionDialogBinding.inflate(inflater, null, false);
+        val inflater = requireActivity().layoutInflater
+        binding = SetupEncryptionDialogBinding.inflate(inflater, null, false)
 
         // Setup layout
-        viewThemeUtils.material.colorTextInputLayout(binding.encryptionPasswordInputContainer);
+        viewThemeUtils?.material?.colorTextInputLayout(binding.encryptionPasswordInputContainer)
 
-        return createDialog(binding.getRoot());
+        return createDialog(binding.root)
     }
 
-    @NonNull
-    private Dialog createDialog(View v) {
-        MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(v.getContext());
-        builder.setView(v).setPositiveButton(R.string.common_ok, null)
-            .setNeutralButton(R.string.common_cancel, (dialog, which) -> {
-                dialog.cancel();
-            })
-            .setTitle(R.string.end_to_end_encryption_title);
-
-        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(v.getContext(), builder);
-
-        Dialog dialog = builder.create();
-        dialog.setCanceledOnTouchOutside(false);
-
-        dialog.setOnShowListener(dialog1 -> {
-
-            Button button = ((AlertDialog) dialog1).getButton(AlertDialog.BUTTON_POSITIVE);
-            button.setOnClickListener(view -> {
-                switch (keyResult) {
-                    case KEY_CREATED:
-                        Log_OC.d(TAG, "New keys generated and stored.");
-
-                        dialog1.dismiss();
-
-                        notifyResult();
-                        break;
-
-                    case KEY_EXISTING_USED:
-                        Log_OC.d(TAG, "Decrypt private key");
+    private fun createDialog(v: View): Dialog {
 
-                        binding.encryptionStatus.setText(R.string.end_to_end_encryption_decrypting);
+        val builder = MaterialAlertDialogBuilder(v.context)
 
-                        try {
-                            String privateKey = task.get();
-                            String mnemonicUnchanged = binding.encryptionPasswordInput.getText().toString();
-                            String mnemonic = binding.encryptionPasswordInput.getText().toString().replaceAll("\\s", "")
-                                .toLowerCase(Locale.ROOT);
-                            String decryptedPrivateKey = EncryptionUtils.decryptPrivateKey(privateKey,
-                                                                                           mnemonic);
+        builder
+            .setView(v)
+            .setPositiveButton(R.string.common_ok, null)
+            .setNegativeButton(R.string.common_cancel) { dialog: DialogInterface, _: Int -> dialog.cancel() }
+            .setTitle(R.string.end_to_end_encryption_title)
 
-                            arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
-                                                                        EncryptionUtils.PRIVATE_KEY, decryptedPrivateKey);
+        viewThemeUtils?.dialog?.colorMaterialAlertDialogBackground(v.context, builder)
 
-                            dialog1.dismiss();
-                            Log_OC.d(TAG, "Private key successfully decrypted and stored");
-
-                            arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
-                                                                        EncryptionUtils.MNEMONIC,
-                                                                        mnemonicUnchanged);
-
-                            // check if private key and public key match
-                            String publicKey = arbitraryDataProvider.getValue(user.getAccountName(),
-                                                                              EncryptionUtils.PUBLIC_KEY);
-
-                            byte[] key1 = generateKey();
-                            String base64encodedKey = encodeBytesToBase64String(key1);
-
-                            String encryptedString = EncryptionUtils.encryptStringAsymmetric(base64encodedKey,
-                                                                                             publicKey);
-                            String decryptedString = decryptStringAsymmetric(encryptedString,
-                                                                             decryptedPrivateKey);
-
-                            byte[] key2 = decodeStringToBase64Bytes(decryptedString);
-
-                            if (!Arrays.equals(key1, key2)) {
-                                throw new Exception("Keys do not match");
-                            }
-
-                            notifyResult();
-
-                        } catch (Exception e) {
-                            binding.encryptionStatus.setText(R.string.end_to_end_encryption_wrong_password);
-                            Log_OC.d(TAG, "Error while decrypting private key: " + e.getMessage());
-                        }
-                        break;
+        val dialog: Dialog = builder.create()
+        dialog.setCanceledOnTouchOutside(false)
+        dialog.setOnShowListener { dialog1: DialogInterface ->
+            val button = (dialog1 as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
+            button.setOnClickListener { positiveButtonOnClick(dialog) }
+        }
 
-                    case KEY_GENERATE:
-                        binding.encryptionPassphrase.setVisibility(View.GONE);
-                        positiveButton.setVisibility(View.GONE);
-                        neutralButton.setVisibility(View.GONE);
-                        getDialog().setTitle(R.string.end_to_end_encryption_storing_keys);
+        return dialog
+    }
 
-                        GenerateNewKeysAsyncTask newKeysTask = new GenerateNewKeysAsyncTask(requireContext());
-                        newKeysTask.execute();
-                        break;
+    private fun positiveButtonOnClick(dialog: DialogInterface) {
+        when (keyResult) {
+            KEY_CREATED -> {
+                Log_OC.d(TAG, "New keys generated and stored.")
+                dialog.dismiss()
+                notifyResult()
+            }
+            KEY_EXISTING_USED -> {
+                decryptPrivateKey(dialog)
+            }
 
-                    default:
-                        dialog1.dismiss();
-                        break;
-                }
-            });
-        });
-        return dialog;
+            KEY_GENERATE -> {
+                generateKey()
+            }
+            else -> dialog.dismiss()
+        }
     }
 
-    private void notifyResult() {
-        final Fragment targetFragment = getTargetFragment();
-        if (targetFragment != null) {
-            targetFragment.onActivityResult(getTargetRequestCode(),
-                                            SETUP_ENCRYPTION_RESULT_CODE, getResultIntent());
+    private fun decryptPrivateKey(dialog: DialogInterface) {
+        Log_OC.d(TAG, "Decrypt private key")
+        binding.encryptionStatus.setText(R.string.end_to_end_encryption_decrypting)
+
+        try {
+            val privateKey = task?.get()
+            val mnemonicUnchanged = binding.encryptionPasswordInput.text.toString()
+            val mnemonic =
+                binding.encryptionPasswordInput.text.toString().replace("\\s".toRegex(), "")
+                    .lowercase()
+            val decryptedPrivateKey = EncryptionUtils.decryptPrivateKey(
+                privateKey,
+                mnemonic
+            )
+
+            val accountName = user?.accountName ?: return
+
+            arbitraryDataProvider?.storeOrUpdateKeyValue(
+                accountName,
+                EncryptionUtils.PRIVATE_KEY, decryptedPrivateKey
+            )
+            dialog.dismiss()
+
+            Log_OC.d(TAG, "Private key successfully decrypted and stored")
+
+            arbitraryDataProvider?.storeOrUpdateKeyValue(
+                accountName,
+                EncryptionUtils.MNEMONIC,
+                mnemonicUnchanged
+            )
+
+            // check if private key and public key match
+            val publicKey = arbitraryDataProvider?.getValue(
+                accountName,
+                EncryptionUtils.PUBLIC_KEY
+            )
+
+            val firstKey = EncryptionUtils.generateKey()
+            val base64encodedKey = EncryptionUtils.encodeBytesToBase64String(firstKey)
+            val encryptedString = EncryptionUtils.encryptStringAsymmetric(
+                base64encodedKey,
+                publicKey
+            )
+            val decryptedString = EncryptionUtils.decryptStringAsymmetric(
+                encryptedString,
+                decryptedPrivateKey
+            )
+            val secondKey = EncryptionUtils.decodeStringToBase64Bytes(decryptedString)
+
+            if (!Arrays.equals(firstKey, secondKey)) {
+                throw Exception("Keys do not match")
+            }
+
+            notifyResult()
+        } catch (e: Exception) {
+            binding.encryptionStatus.setText(R.string.end_to_end_encryption_wrong_password)
+            Log_OC.d(TAG, "Error while decrypting private key: " + e.message)
         }
-        getParentFragmentManager().setFragmentResult(RESULT_REQUEST_KEY, getResultBundle());
     }
 
-    @NonNull
-    private Intent getResultIntent() {
-        Intent intentCreated = new Intent();
-        intentCreated.putExtra(SUCCESS, true);
-        intentCreated.putExtra(ARG_POSITION, getArguments().getInt(ARG_POSITION));
-        return intentCreated;
+    private fun generateKey() {
+        binding.encryptionPassphrase.visibility = View.GONE
+        positiveButton?.visibility = View.GONE
+        negativeButton?.visibility = View.GONE
+
+        dialog?.setTitle(R.string.end_to_end_encryption_storing_keys)
+
+        val newKeysTask = GenerateNewKeysAsyncTask(requireContext())
+        newKeysTask.execute()
     }
 
-    @NonNull
-    private Bundle getResultBundle() {
-        final Bundle bundle = new Bundle();
-        bundle.putBoolean(SUCCESS, true);
-        bundle.putInt(ARG_POSITION, getArguments().getInt(ARG_POSITION));
-        return bundle;
+    private fun notifyResult() {
+        val targetFragment = targetFragment
+        targetFragment?.onActivityResult(
+            targetRequestCode,
+            SETUP_ENCRYPTION_RESULT_CODE, resultIntent
+        )
+        parentFragmentManager.setFragmentResult(RESULT_REQUEST_KEY, resultBundle)
     }
 
+    private val resultIntent: Intent
+        get() {
+            val intentCreated = Intent()
+            intentCreated.putExtra(SUCCESS, true)
+            intentCreated.putExtra(ARG_POSITION, requireArguments().getInt(ARG_POSITION))
+            return intentCreated
+        }
+    private val resultBundle: Bundle
+        get() {
+            val bundle = Bundle()
+            bundle.putBoolean(SUCCESS, true)
+            bundle.putInt(ARG_POSITION, requireArguments().getInt(ARG_POSITION))
+            return bundle
+        }
 
-    @Override
-    public void onCancel(@NonNull DialogInterface dialog) {
-        super.onCancel(dialog);
-        final Bundle bundle = new Bundle();
-        bundle.putBoolean(RESULT_KEY_CANCELLED, true);
-        getParentFragmentManager().setFragmentResult(RESULT_REQUEST_KEY, bundle);
+    override fun onCancel(dialog: DialogInterface) {
+        super.onCancel(dialog)
+        val bundle = Bundle()
+        bundle.putBoolean(RESULT_KEY_CANCELLED, true)
+        parentFragmentManager.setFragmentResult(RESULT_REQUEST_KEY, bundle)
     }
 
-    @Override
-    public void onSaveInstanceState(@NonNull Bundle outState) {
-        outState.putStringArrayList(MNEMONIC, keyWords);
-        super.onSaveInstanceState(outState);
+    override fun onSaveInstanceState(outState: Bundle) {
+        outState.putStringArrayList(EncryptionUtils.MNEMONIC, keyWords)
+        super.onSaveInstanceState(outState)
     }
 
-    public class DownloadKeysAsyncTask extends AsyncTask<Void, Void, String> {
-        private final WeakReference<Context> mWeakContext;
-
-        public DownloadKeysAsyncTask(Context context) {
-            mWeakContext = new WeakReference<>(context);
-        }
-
-        @Override
-        protected void onPreExecute() {
-            super.onPreExecute();
+    @SuppressLint("StaticFieldLeak")
+    inner class DownloadKeysAsyncTask(context: Context) : AsyncTask<Void?, Void?, String?>() {
+        private val mWeakContext: WeakReference<Context>
 
-            binding.encryptionStatus.setText(R.string.end_to_end_encryption_retrieving_keys);
-            positiveButton.setVisibility(View.INVISIBLE);
+        init {
+            mWeakContext = WeakReference(context)
         }
 
-        @Override
-        protected String doInBackground(Void... voids) {
+        @Deprecated("Deprecated in Java")
+        override fun doInBackground(vararg params: Void?): String? {
             // fetch private/public key
             // if available
             //  - store public key
             //  - decrypt private key, store unencrypted private key in database
-
-            Context context = mWeakContext.get();
-            GetPublicKeyOperation publicKeyOperation = new GetPublicKeyOperation();
-            if (user != null) {
-                RemoteOperationResult<String> publicKeyResult = publicKeyOperation.execute(user, context);
-
-                if (publicKeyResult.isSuccess()) {
-                    Log_OC.d(TAG, "public key successful downloaded for " + user.getAccountName());
-
-                    String publicKeyFromServer = publicKeyResult.getResultData();
-                    if (arbitraryDataProvider != null) {
-                        arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
-                                                                    EncryptionUtils.PUBLIC_KEY,
-                                                                    publicKeyFromServer);
-                    } else {
-                        return null;
-                    }
+            val context = mWeakContext.get()
+            val publicKeyOperation = GetPublicKeyOperation()
+            val user = user ?: return null
+
+            val publicKeyResult = publicKeyOperation.execute(user, context)
+
+            if (publicKeyResult.isSuccess) {
+                Log_OC.d(TAG, "public key successful downloaded for " + user.accountName)
+
+                val publicKeyFromServer = publicKeyResult.resultData
+                if (arbitraryDataProvider != null) {
+                    arbitraryDataProvider?.storeOrUpdateKeyValue(
+                        user.accountName,
+                        EncryptionUtils.PUBLIC_KEY,
+                        publicKeyFromServer
+                    )
                 } else {
-                    return null;
+                    return null
                 }
+            } else {
+                return null
+            }
 
-                RemoteOperationResult<com.owncloud.android.lib.ocs.responses.PrivateKey> privateKeyResult =
-                    new GetPrivateKeyOperation().execute(user, context);
+            val privateKeyResult = GetPrivateKeyOperation().execute(user, context)
+            if (privateKeyResult.isSuccess) {
+                Log_OC.d(TAG, "private key successful downloaded for " + user!!.accountName)
+                keyResult = KEY_EXISTING_USED
+                return privateKeyResult.resultData.getKey()
+            }
 
-                if (privateKeyResult.isSuccess()) {
-                    Log_OC.d(TAG, "private key successful downloaded for " + user.getAccountName());
+            return null
+        }
 
-                    keyResult = KEY_EXISTING_USED;
-                    return privateKeyResult.getResultData().getKey();
-                }
-            }
-            return null;
+        @Deprecated("Deprecated in Java")
+        override fun onPreExecute() {
+            super.onPreExecute()
+
+            binding.encryptionStatus.setText(R.string.end_to_end_encryption_retrieving_keys)
+            positiveButton?.visibility = View.INVISIBLE
         }
 
-        @Override
-        protected void onPostExecute(String privateKey) {
-            super.onPostExecute(privateKey);
+        @Deprecated("Deprecated in Java")
+        override fun onPostExecute(privateKey: String?) {
+            super.onPostExecute(privateKey)
 
-            Context context = mWeakContext.get();
+            val context = mWeakContext.get()
             if (context == null) {
-                Log_OC.e(TAG, "Context lost after fetching private keys.");
-                return;
+                Log_OC.e(TAG, "Context lost after fetching private keys.")
+                return
             }
-
             if (privateKey == null) {
                 // first show info
                 try {
-                    if (keyWords == null || keyWords.isEmpty()) {
-                        keyWords = EncryptionUtils.getRandomWords(12, context);
+                    if (keyWords == null || keyWords!!.isEmpty()) {
+                        keyWords = EncryptionUtils.getRandomWords(12, context)
                     }
-                    showMnemonicInfo();
-                } catch (IOException e) {
-                    binding.encryptionStatus.setText(R.string.common_error);
+                    showMnemonicInfo()
+                } catch (e: IOException) {
+                    binding.encryptionStatus.setText(R.string.common_error)
                 }
-            } else if (!privateKey.isEmpty()) {
-                binding.encryptionStatus.setText(R.string.end_to_end_encryption_enter_password);
-                binding.encryptionPasswordInputContainer.setVisibility(View.VISIBLE);
-                positiveButton.setVisibility(View.VISIBLE);
+            } else if (privateKey.isNotEmpty()) {
+                binding.encryptionStatus.setText(R.string.end_to_end_encryption_enter_password)
+                binding.encryptionPasswordInputContainer.visibility = View.VISIBLE
+                positiveButton?.visibility = View.VISIBLE
             } else {
-                Log_OC.e(TAG, "Got empty private key string");
+                Log_OC.e(TAG, "Got empty private key string")
             }
         }
     }
 
-    public class GenerateNewKeysAsyncTask extends AsyncTask<Void, Void, String> {
+    @SuppressLint("StaticFieldLeak")
+    inner class GenerateNewKeysAsyncTask(context: Context) : AsyncTask<Void?, Void?, String>() {
+        private val mWeakContext: WeakReference<Context>
 
-        private final WeakReference<Context> mWeakContext;
-
-        public GenerateNewKeysAsyncTask(Context context) {
-            mWeakContext = new WeakReference<>(context);
+        init {
+            mWeakContext = WeakReference(context)
         }
 
-        @Override
-        protected void onPreExecute() {
-            super.onPreExecute();
-
-            binding.encryptionStatus.setText(R.string.end_to_end_encryption_generating_keys);
+        @Deprecated("Deprecated in Java")
+        override fun onPreExecute() {
+            super.onPreExecute()
+            binding.encryptionStatus.setText(R.string.end_to_end_encryption_generating_keys)
         }
 
-        @Override
-        protected String doInBackground(Void... voids) {
+        @Deprecated("Deprecated in Java")
+        override fun doInBackground(vararg voids: Void?): String {
             //  - create CSR, push to server, store returned public key in database
             //  - encrypt private key, push key to server, store unencrypted private key in database
-
             try {
-                Context context  = mWeakContext.get();
-
-                String publicKeyString;
+                val context = mWeakContext.get()
+                val publicKeyString: String
 
                 // Create public/private key pair
-                KeyPair keyPair = EncryptionUtils.generateKeyPair();
+                val keyPair = EncryptionUtils.generateKeyPair()
 
                 // create CSR
-                AccountManager accountManager = AccountManager.get(context);
-                String userId = accountManager.getUserData(user.toPlatformAccount(), AccountUtils.Constants.KEY_USER_ID);
-                String urlEncoded = CsrHelper.generateCsrPemEncodedString(keyPair, userId);
+                val accountManager = AccountManager.get(context)
+                val user = user ?: return ""
 
-                SendCSROperation operation = new SendCSROperation(urlEncoded);
-                RemoteOperationResult result = operation.execute(user, context);
-
-                if (result.isSuccess()) {
-                    publicKeyString = (String) result.getData().get(0);
+                val userId = accountManager.getUserData(user.toPlatformAccount(), AccountUtils.Constants.KEY_USER_ID)
+                val urlEncoded = CsrHelper.generateCsrPemEncodedString(keyPair, userId)
+                val operation = SendCSROperation(urlEncoded)
+                val result = operation.execute(user, context)
 
+                if (result.isSuccess) {
+                    publicKeyString = result.data[0] as String
                     if (!EncryptionUtils.isMatchingKeys(keyPair, publicKeyString)) {
-                        throw new RuntimeException("Wrong CSR returned");
+                        throw RuntimeException("Wrong CSR returned")
                     }
-
-                    Log_OC.d(TAG, "public key success");
+                    Log_OC.d(TAG, "public key success")
                 } else {
-                    keyResult = KEY_FAILED;
-                    return "";
+                    keyResult = KEY_FAILED
+                    return ""
                 }
 
-                PrivateKey privateKey = keyPair.getPrivate();
-                String privateKeyString = EncryptionUtils.encodeBytesToBase64String(privateKey.getEncoded());
-                String privatePemKeyString = EncryptionUtils.privateKeyToPEM(privateKey);
-                String encryptedPrivateKey = EncryptionUtils.encryptPrivateKey(privatePemKeyString,
-                                                                               generateMnemonicString(false));
+                val privateKey = keyPair.private
+                val privateKeyString = EncryptionUtils.encodeBytesToBase64String(privateKey.encoded)
+                val privatePemKeyString = EncryptionUtils.privateKeyToPEM(privateKey)
+                val encryptedPrivateKey = EncryptionUtils.encryptPrivateKey(
+                    privatePemKeyString,
+                    generateMnemonicString(false)
+                )
 
                 // upload encryptedPrivateKey
-                StorePrivateKeyOperation storePrivateKeyOperation = new StorePrivateKeyOperation(encryptedPrivateKey);
-                RemoteOperationResult storePrivateKeyResult = storePrivateKeyOperation.execute(user, context);
-
-                if (storePrivateKeyResult.isSuccess()) {
-                    Log_OC.d(TAG, "private key success");
-
-                    arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
-                                                                EncryptionUtils.PRIVATE_KEY,
-                                                                privateKeyString);
-                    arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
-                                                                EncryptionUtils.PUBLIC_KEY,
-                                                                publicKeyString);
-                    arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
-                                                                EncryptionUtils.MNEMONIC,
-                                                                generateMnemonicString(true));
-
-                    keyResult = KEY_CREATED;
-                    return (String) storePrivateKeyResult.getData().get(0);
+                val storePrivateKeyOperation = StorePrivateKeyOperation(encryptedPrivateKey)
+                val storePrivateKeyResult = storePrivateKeyOperation.execute(user, context)
+                if (storePrivateKeyResult.isSuccess) {
+                    Log_OC.d(TAG, "private key success")
+                    arbitraryDataProvider!!.storeOrUpdateKeyValue(
+                        user.accountName,
+                        EncryptionUtils.PRIVATE_KEY,
+                        privateKeyString
+                    )
+                    arbitraryDataProvider!!.storeOrUpdateKeyValue(
+                        user.accountName,
+                        EncryptionUtils.PUBLIC_KEY,
+                        publicKeyString
+                    )
+                    arbitraryDataProvider!!.storeOrUpdateKeyValue(
+                        user.accountName,
+                        EncryptionUtils.MNEMONIC,
+                        generateMnemonicString(true)
+                    )
+                    keyResult = KEY_CREATED
+
+                    return storePrivateKeyResult.data[0] as String
                 } else {
-                    DeletePublicKeyOperation deletePublicKeyOperation = new DeletePublicKeyOperation();
-                    deletePublicKeyOperation.execute(user, context);
+                    val deletePublicKeyOperation = DeletePublicKeyOperation()
+                    deletePublicKeyOperation.execute(user, context)
                 }
-            } catch (Exception e) {
-                Log_OC.e(TAG, e.getMessage());
+            } catch (e: Exception) {
+                Log_OC.e(TAG, e.message)
             }
-
-            keyResult = KEY_FAILED;
-            return "";
+            keyResult = KEY_FAILED
+            return ""
         }
 
-        @Override
-        protected void onPostExecute(String s) {
-            super.onPostExecute(s);
-
-            Context context = mWeakContext.get();
+        @Deprecated("Deprecated in Java")
+        override fun onPostExecute(s: String) {
+            super.onPostExecute(s)
+            val context = mWeakContext.get()
             if (context == null) {
-                Log_OC.e(TAG, "Context lost after generating new private keys.");
-                return;
+                Log_OC.e(TAG, "Context lost after generating new private keys.")
+                return
             }
-
             if (s.isEmpty()) {
-                errorSavingKeys();
+                errorSavingKeys()
             } else {
-                if (getDialog() == null) {
-                    Log_OC.e(TAG, "Dialog is null cannot proceed further.");
-                    return;
+                if (dialog == null) {
+                    Log_OC.e(TAG, "Dialog is null cannot proceed further.")
+                    return
                 }
-
-                requireDialog().dismiss();
-                notifyResult();
+                requireDialog().dismiss()
+                notifyResult()
             }
         }
     }
 
-    private String generateMnemonicString(boolean withWhitespace) {
-        StringBuilder stringBuilder = new StringBuilder();
-
-        for (String string : keyWords) {
-            stringBuilder.append(string);
+    private fun generateMnemonicString(withWhitespace: Boolean): String {
+        val stringBuilder = StringBuilder()
+        for (string in keyWords!!) {
+            stringBuilder.append(string)
             if (withWhitespace) {
-                stringBuilder.append(' ');
+                stringBuilder.append(' ')
             }
         }
-
-        return stringBuilder.toString();
+        return stringBuilder.toString()
     }
 
     @VisibleForTesting
-    public void showMnemonicInfo() {
-        if (getDialog() == null) {
-            Log_OC.e(TAG, "Dialog is null cannot proceed further.");
-            return;
+    fun showMnemonicInfo() {
+        if (dialog == null) {
+            Log_OC.e(TAG, "Dialog is null cannot proceed further.")
+            return
         }
-        requireDialog().setTitle(R.string.end_to_end_encryption_passphrase_title);
-
-        binding.encryptionStatus.setText(R.string.end_to_end_encryption_keywords_description);
-        viewThemeUtils.material.colorTextInputLayout(binding.encryptionPasswordInputContainer);
-
-        binding.encryptionPassphrase.setText(generateMnemonicString(true));
-
-        binding.encryptionPassphrase.setVisibility(View.VISIBLE);
-        positiveButton.setText(R.string.end_to_end_encryption_confirm_button);
-        positiveButton.setVisibility(View.VISIBLE);
-
-        neutralButton.setVisibility(View.VISIBLE);
-        viewThemeUtils.platform.colorTextButtons(positiveButton, neutralButton);
-
-        keyResult = KEY_GENERATE;
+        requireDialog().setTitle(R.string.end_to_end_encryption_passphrase_title)
+        binding.encryptionStatus.setText(R.string.end_to_end_encryption_keywords_description)
+        viewThemeUtils!!.material.colorTextInputLayout(binding.encryptionPasswordInputContainer)
+        binding.encryptionPassphrase.text = generateMnemonicString(true)
+        binding.encryptionPassphrase.visibility = View.VISIBLE
+        positiveButton!!.setText(R.string.end_to_end_encryption_confirm_button)
+        positiveButton!!.visibility = View.VISIBLE
+        negativeButton!!.visibility = View.VISIBLE
+        viewThemeUtils!!.platform.colorTextButtons(positiveButton!!, negativeButton!!)
+        keyResult = KEY_GENERATE
     }
 
     @VisibleForTesting
-    public void errorSavingKeys() {
-        if (getDialog() == null) {
-            Log_OC.e(TAG, "Dialog is null cannot proceed further.");
-            return;
+    fun errorSavingKeys() {
+        if (dialog == null) {
+            Log_OC.e(TAG, "Dialog is null cannot proceed further.")
+            return
         }
 
-        keyResult = KEY_FAILED;
+        keyResult = KEY_FAILED
+        requireDialog().setTitle(R.string.common_error)
+        binding.encryptionStatus.setText(R.string.end_to_end_encryption_unsuccessful)
+        binding.encryptionPassphrase.visibility = View.GONE
+
+        positiveButton?.setText(R.string.end_to_end_encryption_dialog_close)
+        positiveButton?.visibility = View.VISIBLE
 
-        requireDialog().setTitle(R.string.common_error);
-        binding.encryptionStatus.setText(R.string.end_to_end_encryption_unsuccessful);
-        binding.encryptionPassphrase.setVisibility(View.GONE);
-        positiveButton.setText(R.string.end_to_end_encryption_dialog_close);
-        positiveButton.setVisibility(View.VISIBLE);
-        viewThemeUtils.platform.colorTextButtons(positiveButton);
+        if (positiveButton != null) {
+            viewThemeUtils?.platform?.colorTextButtons(positiveButton!!)
+        }
     }
 
     @VisibleForTesting
-    public void setMnemonic(ArrayList<String> keyWords) {
-        this.keyWords = keyWords;
+    fun setMnemonic(keyWords: ArrayList<String>?) {
+        this.keyWords = keyWords
+    }
+
+    companion object {
+        const val SUCCESS = "SUCCESS"
+        const val SETUP_ENCRYPTION_RESULT_CODE = 101
+        const val SETUP_ENCRYPTION_REQUEST_CODE = 100
+        const val SETUP_ENCRYPTION_DIALOG_TAG = "SETUP_ENCRYPTION_DIALOG_TAG"
+        const val ARG_POSITION = "ARG_POSITION"
+        const val RESULT_REQUEST_KEY = "RESULT_REQUEST"
+        const val RESULT_KEY_CANCELLED = "IS_CANCELLED"
+        private const val ARG_USER = "ARG_USER"
+        private val TAG = SetupEncryptionDialogFragment::class.java.simpleName
+        private const val KEY_CREATED = "KEY_CREATED"
+        private const val KEY_EXISTING_USED = "KEY_EXISTING_USED"
+        private const val KEY_FAILED = "KEY_FAILED"
+        private const val KEY_GENERATE = "KEY_GENERATE"
+
+        /**
+         * Public factory method to create new SetupEncryptionDialogFragment instance
+         *
+         * @return Dialog ready to show.
+         */
+        @JvmStatic
+        fun newInstance(user: User?, position: Int): SetupEncryptionDialogFragment {
+            val fragment = SetupEncryptionDialogFragment()
+            val args = Bundle()
+            args.putParcelable(ARG_USER, user)
+            args.putInt(ARG_POSITION, position)
+            fragment.arguments = args
+            return fragment
+        }
     }
-}
+}

+ 2 - 2
app/src/main/res/layout/setup_encryption_dialog.xml

@@ -26,14 +26,14 @@
     android:orientation="vertical"
     android:padding="@dimen/dialog_padding">
 
-    <TextView
+    <com.google.android.material.textview.MaterialTextView
         android:id="@+id/encryption_status"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/standard_margin"
         tools:text="@string/end_to_end_encryption_keywords_description" />
 
-    <TextView
+    <com.google.android.material.textview.MaterialTextView
         android:id="@+id/encryption_passphrase"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"