From 9acad2abf68b64d3ca70b5263a72dfe3d5ff0081 Mon Sep 17 00:00:00 2001 From: Aditya Wasan Date: Wed, 13 Nov 2019 00:55:56 +0530 Subject: Convert java files to kotlin (#570) * Break SshKeyGen into multiple files * Use tinted material button * Convert PasswordStore to kotlin * Remove SshKeyGen * Remove explicit imports and other tweaks Signed-off-by: Aditya Wasan --- .../zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt | 69 +++++++++++++++++ .../zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt | 35 +++++++++ .../zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt | 90 ++++++++++++++++++++++ .../com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt | 77 ++++++++++++++++++ 4 files changed, 271 insertions(+) create mode 100644 app/src/main/java/com/zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt create mode 100644 app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt create mode 100644 app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt create mode 100644 app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt (limited to 'app/src/main/java/com/zeapo/pwdstore/sshkeygen') diff --git a/app/src/main/java/com/zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt new file mode 100644 index 00000000..5f27090f --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt @@ -0,0 +1,69 @@ +/* + * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package com.zeapo.pwdstore.sshkeygen + +import android.annotation.SuppressLint +import android.app.Dialog +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.os.Bundle +import android.view.View +import android.widget.TextView +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.zeapo.pwdstore.R +import java.io.File +import java.nio.charset.StandardCharsets +import org.apache.commons.io.FileUtils + +class ShowSshKeyFragment : DialogFragment() { + + private lateinit var activity: SshKeyGenActivity + private lateinit var builder: MaterialAlertDialogBuilder + private lateinit var publicKey: TextView + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + activity = requireActivity() as SshKeyGenActivity + builder = MaterialAlertDialogBuilder(activity) + } + + @SuppressLint("InflateParams") + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val view = activity.layoutInflater.inflate(R.layout.fragment_show_ssh_key, null) + publicKey = view.findViewById(R.id.public_key) + readKeyFromFile() + createMaterialDialog(view) + val ad = builder.create() + ad.setOnShowListener { + val b = ad.getButton(AlertDialog.BUTTON_NEUTRAL) + b.setOnClickListener { + val clipboard = activity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("public key", publicKey.text.toString()) + clipboard.setPrimaryClip(clip) + } + } + return ad + } + + private fun createMaterialDialog(view: View) { + builder.setView(view) + builder.setTitle(getString(R.string.your_public_key)) + builder.setPositiveButton(getString(R.string.dialog_ok)) { _, _ -> activity.finish() } + builder.setNegativeButton(getString(R.string.dialog_cancel), null) + builder.setNeutralButton(resources.getString(R.string.ssh_keygen_copy), null) + } + + private fun readKeyFromFile() { + val file = File(activity.filesDir.toString() + "/.ssh_key.pub") + try { + publicKey.text = FileUtils.readFileToString(file, StandardCharsets.UTF_8) + } catch (e: Exception) { + e.printStackTrace() + } + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt new file mode 100644 index 00000000..21d82a3b --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt @@ -0,0 +1,35 @@ +/* + * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package com.zeapo.pwdstore.sshkeygen + +import android.os.Bundle +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity + +class SshKeyGenActivity : AppCompatActivity() { + + public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + title = "Generate SSH Key" + if (savedInstanceState == null) { + supportFragmentManager + .beginTransaction() + .replace(android.R.id.content, SshKeyGenFragment()) + .commit() + } + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + // The back arrow in the action bar should act the same as the back button. + return when (item.itemId) { + android.R.id.home -> { + onBackPressed() + true + } + else -> super.onOptionsItemSelected(item) + } + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt new file mode 100644 index 00000000..19011758 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt @@ -0,0 +1,90 @@ +/* + * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package com.zeapo.pwdstore.sshkeygen + +import android.os.Bundle +import android.text.InputType +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.ArrayAdapter +import android.widget.Button +import android.widget.CheckBox +import android.widget.EditText +import android.widget.Spinner +import androidx.core.content.getSystemService +import androidx.fragment.app.Fragment +import com.google.android.material.textfield.TextInputEditText +import com.zeapo.pwdstore.R + +class SshKeyGenFragment : Fragment() { + + private lateinit var checkBox: CheckBox + private lateinit var comment: EditText + private lateinit var generate: Button + private lateinit var passphrase: TextInputEditText + private lateinit var spinner: Spinner + private lateinit var activity: SshKeyGenActivity + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_ssh_keygen, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + activity = requireActivity() as SshKeyGenActivity + findViews(view) + val lengths = arrayOf(2048, 4096) + val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, lengths) + spinner.adapter = adapter + generate.setOnClickListener { generate() } + checkBox.setOnCheckedChangeListener { _, isChecked: Boolean -> + val selection = passphrase.selectionEnd + if (isChecked) { + passphrase.inputType = ( + InputType.TYPE_CLASS_TEXT + or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) + } else { + passphrase.inputType = ( + InputType.TYPE_CLASS_TEXT + or InputType.TYPE_TEXT_VARIATION_PASSWORD) + } + passphrase.setSelection(selection) + } + } + + private fun findViews(view: View) { + checkBox = view.findViewById(R.id.show_passphrase) + comment = view.findViewById(R.id.comment) + generate = view.findViewById(R.id.generate) + passphrase = view.findViewById(R.id.passphrase) + spinner = view.findViewById(R.id.length) + } + + // Invoked when 'Generate' button of SshKeyGenFragment clicked. Generates a + // private and public key, then replaces the SshKeyGenFragment with a + // ShowSshKeyFragment which displays the public key. + fun generate() { + val length = (spinner.selectedItem as Int).toString() + val passphrase = passphrase.text.toString() + val comment = comment.text.toString() + KeyGenerateTask(activity).execute(length, passphrase, comment) + hideKeyboard() + } + + private fun hideKeyboard() { + val imm = activity.getSystemService() + var view = activity.currentFocus + if (view == null) { + view = View(activity) + } + imm?.hideSoftInputFromWindow(view.windowToken, 0) + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt new file mode 100644 index 00000000..194d1023 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt @@ -0,0 +1,77 @@ +/* + * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package com.zeapo.pwdstore.sshkeygen + +import android.app.ProgressDialog +import android.os.AsyncTask +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.DialogFragment +import androidx.preference.PreferenceManager +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.jcraft.jsch.JSch +import com.jcraft.jsch.KeyPair +import com.zeapo.pwdstore.R +import java.io.File +import java.io.FileOutputStream +import java.lang.ref.WeakReference + +class KeyGenerateTask(activity: AppCompatActivity) : AsyncTask() { + private var pd: ProgressDialog? = null + private val weakReference = WeakReference(activity) + override fun onPreExecute() { + super.onPreExecute() + pd = ProgressDialog.show(weakReference.get(), "", "Generating keys") + } + + override fun doInBackground(vararg strings: String?): Exception? { + val length = strings[0]?.toInt() + val passphrase = strings[1] + val comment = strings[2] + val jsch = JSch() + try { + val kp = length?.let { KeyPair.genKeyPair(jsch, KeyPair.RSA, it) } + var file = File(weakReference.get()!!.filesDir.toString() + "/.ssh_key") + var out = FileOutputStream(file, false) + if (passphrase?.isNotEmpty()!!) { + kp?.writePrivateKey(out, passphrase.toByteArray()) + } else { + kp?.writePrivateKey(out) + } + file = File(weakReference.get()!!.filesDir.toString() + "/.ssh_key.pub") + out = FileOutputStream(file, false) + kp?.writePublicKey(out, comment) + return null + } catch (e: Exception) { + e.printStackTrace() + return e + } + } + + override fun onPostExecute(e: Exception?) { + super.onPostExecute(e) + val activity = weakReference.get() + if (activity is AppCompatActivity) { + pd!!.dismiss() + if (e == null) { + Toast.makeText(activity, "SSH-key generated", Toast.LENGTH_LONG).show() + val df: DialogFragment = ShowSshKeyFragment() + df.show(activity.supportFragmentManager, "public_key") + val prefs = PreferenceManager.getDefaultSharedPreferences(weakReference.get()) + val editor = prefs.edit() + editor.putBoolean("use_generated_key", true) + editor.apply() + } else { + MaterialAlertDialogBuilder(weakReference.get()) + .setTitle(activity.getString(R.string.error_generate_ssh_key)) + .setMessage(activity.getString(R.string.ssh_key_error_dialog_text) + e.message) + .setPositiveButton(activity.getString(R.string.dialog_ok), null) + .show() + } + } else { + // TODO: When activity is destroyed + } + } +} -- cgit v1.2.3