2FA codes can now be scanned.
This commit is contained in:
@@ -1,25 +1,42 @@
|
||||
package com.github.mondei1.offpass
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.ColorFilter
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.zxing.integration.android.IntentIntegrator
|
||||
import com.google.zxing.integration.android.IntentResult
|
||||
import dev.turingcomplete.kotlinonetimepassword.GoogleAuthenticator
|
||||
import kotlinx.android.synthetic.main.activity_create.*
|
||||
import kotlinx.coroutines.*
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class CreateActivity : AppCompatActivity() {
|
||||
private var fragment_title: TextInput? = null
|
||||
private var fragment_username: TextInput? = null
|
||||
private var schema: QRSchema? = null
|
||||
|
||||
private var fa_coroutine: Job? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
fragment_title = TextInput.newInstance("Title", "ENTER TITLE", "30dp")
|
||||
fragment_username = TextInput.newInstance("Username", "ENTER USERNAME", "30dp")
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.title_box, fragment_title!!)
|
||||
.replace(R.id.username, fragment_username!!)
|
||||
.commit()
|
||||
|
||||
//this.schema = QRSchema(this)
|
||||
//this.schema!!.decrypted_raw = "%JtuB4O9M42%Gitea|Nicolas|542superGoOD_pW&|klier.nicolas@protonmail.com|\$ul|(\$vb)\$O4|()What's your favorite series%Rick and morty|(2fa)otpauth://totp/OffPass%20Test?secret=d34gfkki5dkd5knifysrpgndd5xb2c7eddwki7ya4pvoisfa5c3ko5pv&issuer=Nicolas%20Klier"
|
||||
//this.schema!!.parse(this)
|
||||
@@ -34,6 +51,80 @@ class CreateActivity : AppCompatActivity() {
|
||||
Log.i("CREATE", "Back got clicked!")
|
||||
finish()
|
||||
}
|
||||
|
||||
fa_input.isFocusable = false
|
||||
|
||||
fa_input.setOnClickListener {
|
||||
if (fa_coroutine != null) {
|
||||
if (fa_coroutine!!.isActive) {
|
||||
// Copy code if already scanend
|
||||
Toast.makeText(this, "Copied!", Toast.LENGTH_SHORT).show()
|
||||
val clip: ClipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clip.setPrimaryClip(ClipData.newPlainText("2FA code", fa_input.text))
|
||||
return@setOnClickListener
|
||||
}
|
||||
}
|
||||
|
||||
// Open QR-Code scanner
|
||||
IntentIntegrator(this)
|
||||
.setPrompt("Scan 2FA secret")
|
||||
.setBeepEnabled(false)
|
||||
.setBarcodeImageEnabled(false)
|
||||
.initiateScan()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat", "SetTextI18n")
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
var result: IntentResult =
|
||||
IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
|
||||
if (result.contents == null) {
|
||||
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show()
|
||||
} else {
|
||||
// We scanned a 2FA code
|
||||
if (result.contents.startsWith("otpauth://totp/")) {
|
||||
fa_progress.visibility = View.VISIBLE
|
||||
val fa_uri = Uri.parse(result.contents)
|
||||
val fa_generator = GoogleAuthenticator(base32secret = fa_uri.getQueryParameter("secret").toString())
|
||||
|
||||
/*val objAnim: ObjectAnimator = ObjectAnimator.ofInt(fa_progress, "progress")
|
||||
objAnim.duration = 300
|
||||
objAnim.interpolator = LinearInterpolator()
|
||||
objAnim.start()*/
|
||||
|
||||
// TODO: There is a bug. When the user changes his current app, this coroutine stops.
|
||||
fa_coroutine = GlobalScope.launch(Dispatchers.Main) {
|
||||
while (true) {
|
||||
fa_input.setText(fa_generator.generate())
|
||||
|
||||
var seconds_remaining = CryptoOperations().getRemainingTOTPTime()
|
||||
Log.i("2FA Generator", "Remaining: $seconds_remaining")
|
||||
|
||||
if (seconds_remaining == 0) seconds_remaining = 30
|
||||
|
||||
// Change color
|
||||
if (seconds_remaining >= 15) {
|
||||
fa_progress.progressTintList = ColorStateList.valueOf(Color.GREEN)
|
||||
} else if (seconds_remaining < 15 && seconds_remaining >= 8) {
|
||||
fa_progress.progressTintList = ColorStateList.valueOf(Color.YELLOW)
|
||||
} else {
|
||||
fa_progress.progressTintList = ColorStateList.valueOf(Color.RED)
|
||||
}
|
||||
|
||||
fa_progress.progress = seconds_remaining
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
|
||||
fa_label.text = "${fa_uri.path?.replace("/", "")} (${fa_uri.getQueryParameter("issuer")})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
fa_coroutine?.cancel(CancellationException("Activity is stopping"))
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user