diff options
author | Harsh Shandilya <msfjarvis@gmail.com> | 2020-06-30 19:21:49 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-30 19:21:49 +0530 |
commit | 5e74507d5b3f3de8a4f0881fa14f87058e9a63fc (patch) | |
tree | ccab0b45fb642074bbe6691c82a7e2f3eedc0c10 /app/src/main/java/com | |
parent | 57f125a4da9f8bad69c2b2e2e6540d245bdd44c4 (diff) |
Allow importing TOTP configuration through QR codes (#903)
Co-authored-by: Fabian Henneke <fabian@henneke.me>
Diffstat (limited to 'app/src/main/java/com')
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt index 81a73988..a9b1219d 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt @@ -17,6 +17,8 @@ import androidx.core.widget.doOnTextChanged import androidx.lifecycle.lifecycleScope import com.github.ajalt.timberkt.e import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.google.zxing.integration.android.IntentIntegrator +import com.google.zxing.integration.android.IntentIntegrator.QR_CODE import com.zeapo.pwdstore.R import com.zeapo.pwdstore.autofill.oreo.AutofillPreferences import com.zeapo.pwdstore.autofill.oreo.DirectoryStructure @@ -62,6 +64,33 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB with(binding) { setContentView(root) generatePassword.setOnClickListener { generatePassword() } + otpImportButton.setOnClickListener { + registerForActivityResult(StartActivityForResult()) { result -> + if (result.resultCode == RESULT_OK) { + otpImportButton.isVisible = false + val intentResult = IntentIntegrator.parseActivityResult(RESULT_OK, result.data) + val contents = if (intentResult.contents.startsWith("otpauth://")) { + "${intentResult.contents}\n" + } else { + "totp: ${intentResult.contents}\n" + } + val currentExtras = extraContent.text.toString() + if (currentExtras.isNotEmpty() && currentExtras.last() != '\n') + extraContent.append("\n$contents") + else + extraContent.append(contents) + snackbar(message = getString(R.string.otp_import_success)) + } else { + snackbar(message = getString(R.string.otp_import_failure)) + } + }.launch( + IntentIntegrator(this@PasswordCreationActivity) + .setOrientationLocked(false) + .setBeepEnabled(false) + .setDesiredBarcodeFormats(QR_CODE) + .createScanIntent() + ) + } category.apply { if (suggestedName != null || suggestedPass != null || shouldGeneratePassword) { @@ -95,7 +124,7 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB val username = filename.text.toString() val extras = "username:$username\n${extraContent.text}" - filename.setText("") + filename.text?.clear() extraContent.setText(extras) } else { // User wants to disable username encryption, so we extract the @@ -104,20 +133,20 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB val username = entry.username // username should not be null here by the logic in - // updateEncryptUsernameState, but it could still happen due to + // updateViewState, but it could still happen due to // input lag. if (username != null) { filename.setText(username) extraContent.setText(entry.extraContentWithoutAuthData) } } - updateEncryptUsernameState() + updateViewState() } } listOf(filename, extraContent).forEach { - it.doOnTextChanged { _, _, _, _ -> updateEncryptUsernameState() } + it.doOnTextChanged { _, _, _, _ -> updateViewState() } } - updateEncryptUsernameState() + updateViewState() } suggestedPass?.let { password.setText(it) @@ -158,17 +187,18 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB } } - private fun updateEncryptUsernameState() = with(binding) { + private fun updateViewState() = with(binding) { + // Use PasswordEntry to parse extras for username + val entry = PasswordEntry("PLACEHOLDER\n${extraContent.text}") encryptUsername.apply { if (visibility != View.VISIBLE) return@with val hasUsernameInFileName = filename.text.toString().isNotBlank() - // Use PasswordEntry to parse extras for username - val entry = PasswordEntry("PLACEHOLDER\n${extraContent.text}") val hasUsernameInExtras = entry.hasUsername() isEnabled = hasUsernameInFileName xor hasUsernameInExtras isChecked = hasUsernameInExtras } + otpImportButton.isVisible = !entry.hasTotp() } /** |