mirror of
https://github.com/android-password-store/Android-Password-Store
synced 2025-09-01 06:45:19 +00:00
Switch to openpgp-ktx (#565)
Signed-off-by: Harsh Shandilya <msfjarvis@gmail.com>
This commit is contained in:
@@ -80,7 +80,7 @@ dependencies {
|
|||||||
implementation 'com.google.android.material:material:' + versions.material
|
implementation 'com.google.android.material:material:' + versions.material
|
||||||
implementation 'androidx.annotation:annotation:' + versions.annotation
|
implementation 'androidx.annotation:annotation:' + versions.annotation
|
||||||
implementation 'androidx.biometric:biometric:' + versions.biometric
|
implementation 'androidx.biometric:biometric:' + versions.biometric
|
||||||
implementation 'com.github.msfjarvis:openpgp-api:' + versions.openpgp
|
implementation 'com.github.android-password-store:openpgp-ktx:' + versions.openpgp
|
||||||
implementation('org.eclipse.jgit:org.eclipse.jgit:' + versions.jgit) {
|
implementation('org.eclipse.jgit:org.eclipse.jgit:' + versions.jgit) {
|
||||||
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
|
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
|
||||||
}
|
}
|
||||||
|
@@ -42,8 +42,8 @@ import java.time.format.DateTimeFormatter
|
|||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
import java.util.TimeZone
|
import java.util.TimeZone
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpUtils
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import org.openintents.openpgp.util.OpenPgpUtils
|
|
||||||
|
|
||||||
typealias ClickListener = Preference.OnPreferenceClickListener
|
typealias ClickListener = Preference.OnPreferenceClickListener
|
||||||
typealias ChangeListener = Preference.OnPreferenceChangeListener
|
typealias ChangeListener = Preference.OnPreferenceChangeListener
|
||||||
|
@@ -39,11 +39,11 @@ import java.net.MalformedURLException
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import me.msfjarvis.openpgpktx.OpenPgpError
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpServiceConnection
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import org.openintents.openpgp.IOpenPgpService2
|
import org.openintents.openpgp.IOpenPgpService2
|
||||||
import org.openintents.openpgp.OpenPgpError
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi
|
|
||||||
import org.openintents.openpgp.util.OpenPgpServiceConnection
|
|
||||||
|
|
||||||
class AutofillService : AccessibilityService() {
|
class AutofillService : AccessibilityService() {
|
||||||
private var serviceConnection: OpenPgpServiceConnection? = null
|
private var serviceConnection: OpenPgpServiceConnection? = null
|
||||||
@@ -197,11 +197,10 @@ class AutofillService : AccessibilityService() {
|
|||||||
|
|
||||||
// get the app name and find a corresponding password
|
// get the app name and find a corresponding password
|
||||||
val packageManager = packageManager
|
val packageManager = packageManager
|
||||||
var applicationInfo: ApplicationInfo?
|
val applicationInfo: ApplicationInfo? = try {
|
||||||
try {
|
packageManager.getApplicationInfo(event.packageName.toString(), 0)
|
||||||
applicationInfo = packageManager.getApplicationInfo(event.packageName.toString(), 0)
|
|
||||||
} catch (e: PackageManager.NameNotFoundException) {
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
applicationInfo = null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
appName = (if (applicationInfo != null) packageManager.getApplicationLabel(applicationInfo) else "").toString()
|
appName = (if (applicationInfo != null) packageManager.getApplicationLabel(applicationInfo) else "").toString()
|
||||||
@@ -494,10 +493,10 @@ class AutofillService : AccessibilityService() {
|
|||||||
|
|
||||||
val os = ByteArrayOutputStream()
|
val os = ByteArrayOutputStream()
|
||||||
|
|
||||||
val api = OpenPgpApi(this@AutofillService, serviceConnection!!.service)
|
val api = OpenPgpApi(this@AutofillService, serviceConnection!!.service!!)
|
||||||
// TODO we are dropping frames, (did we before??) find out why and maybe make this async
|
// TODO we are dropping frames, (did we before??) find out why and maybe make this async
|
||||||
val result = api.executeApi(data, `is`, os)
|
val result = api.executeApi(data, `is`, os)
|
||||||
when (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
|
when (result?.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||||
OpenPgpApi.RESULT_CODE_SUCCESS -> {
|
OpenPgpApi.RESULT_CODE_SUCCESS -> {
|
||||||
try {
|
try {
|
||||||
val entry = PasswordEntry(os)
|
val entry = PasswordEntry(os)
|
||||||
@@ -568,12 +567,12 @@ class AutofillService : AccessibilityService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inner class OnBoundListener : OpenPgpServiceConnection.OnBound {
|
private inner class OnBoundListener : OpenPgpServiceConnection.OnBound {
|
||||||
override fun onBound(service: IOpenPgpService2) {
|
override fun onBound(service: IOpenPgpService2?) {
|
||||||
decryptAndVerify()
|
decryptAndVerify()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Exception) {
|
override fun onError(e: Exception?) {
|
||||||
e.printStackTrace()
|
e?.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -51,19 +51,19 @@ import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_category
|
|||||||
import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_edit
|
import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_edit
|
||||||
import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_file_edit
|
import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_file_edit
|
||||||
import kotlinx.android.synthetic.main.encrypt_layout.generate_password
|
import kotlinx.android.synthetic.main.encrypt_layout.generate_password
|
||||||
|
import me.msfjarvis.openpgpktx.OpenPgpError
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi.Companion.ACTION_DECRYPT_VERIFY
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi.Companion.RESULT_CODE
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi.Companion.RESULT_CODE_ERROR
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi.Companion.RESULT_CODE_SUCCESS
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi.Companion.RESULT_CODE_USER_INTERACTION_REQUIRED
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi.Companion.RESULT_ERROR
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpApi.Companion.RESULT_INTENT
|
||||||
|
import me.msfjarvis.openpgpktx.util.OpenPgpServiceConnection
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import org.apache.commons.io.FilenameUtils
|
import org.apache.commons.io.FilenameUtils
|
||||||
import org.openintents.openpgp.IOpenPgpService2
|
import org.openintents.openpgp.IOpenPgpService2
|
||||||
import org.openintents.openpgp.OpenPgpError
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi.ACTION_DECRYPT_VERIFY
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi.RESULT_CODE
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi.RESULT_CODE_ERROR
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi.RESULT_CODE_SUCCESS
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi.RESULT_ERROR
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi.RESULT_INTENT
|
|
||||||
import org.openintents.openpgp.util.OpenPgpServiceConnection
|
|
||||||
|
|
||||||
class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
|
class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
|
||||||
private val clipboard: ClipboardManager by lazy {
|
private val clipboard: ClipboardManager by lazy {
|
||||||
@@ -226,13 +226,13 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
|
|||||||
val error: OpenPgpError? = result.getParcelableExtra(RESULT_ERROR)
|
val error: OpenPgpError? = result.getParcelableExtra(RESULT_ERROR)
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
showSnackbar("Error from OpenKeyChain : " + error.message)
|
showSnackbar("Error from OpenKeyChain : " + error.message)
|
||||||
Log.e(TAG, "onError getErrorId:" + error.errorId)
|
Log.e(TAG, "onError getErrorId:" + error.message)
|
||||||
Log.e(TAG, "onError getMessage:" + error.message)
|
Log.e(TAG, "onError getMessage:" + error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initOpenPgpApi() {
|
private fun initOpenPgpApi() {
|
||||||
api = api ?: OpenPgpApi(this, mServiceConnection?.service)
|
api = api ?: OpenPgpApi(this, mServiceConnection!!.service!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun decryptAndVerify(receivedIntent: Intent? = null) {
|
private fun decryptAndVerify(receivedIntent: Intent? = null) {
|
||||||
@@ -242,173 +242,175 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
|
|||||||
val iStream = FileUtils.openInputStream(File(fullPath))
|
val iStream = FileUtils.openInputStream(File(fullPath))
|
||||||
val oStream = ByteArrayOutputStream()
|
val oStream = ByteArrayOutputStream()
|
||||||
|
|
||||||
api?.executeApiAsync(data, iStream, oStream) { result: Intent? ->
|
api?.executeApiAsync(data, iStream, oStream, object : OpenPgpApi.IOpenPgpCallback {
|
||||||
when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) {
|
override fun onReturn(result: Intent?) {
|
||||||
RESULT_CODE_SUCCESS -> {
|
when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) {
|
||||||
try {
|
RESULT_CODE_SUCCESS -> {
|
||||||
val showPassword = settings.getBoolean("show_password", true)
|
try {
|
||||||
val showExtraContent = settings.getBoolean("show_extra_content", true)
|
val showPassword = settings.getBoolean("show_password", true)
|
||||||
|
val showExtraContent = settings.getBoolean("show_extra_content", true)
|
||||||
|
|
||||||
crypto_container_decrypt.visibility = View.VISIBLE
|
crypto_container_decrypt.visibility = View.VISIBLE
|
||||||
|
|
||||||
val monoTypeface = Typeface.createFromAsset(assets, "fonts/sourcecodepro.ttf")
|
val monoTypeface = Typeface.createFromAsset(assets, "fonts/sourcecodepro.ttf")
|
||||||
val entry = PasswordEntry(oStream)
|
val entry = PasswordEntry(oStream)
|
||||||
|
|
||||||
passwordEntry = entry
|
passwordEntry = entry
|
||||||
|
|
||||||
if (intent.getStringExtra("OPERATION") == "EDIT") {
|
if (intent.getStringExtra("OPERATION") == "EDIT") {
|
||||||
editPassword()
|
editPassword()
|
||||||
return@executeApiAsync
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.password.isEmpty()) {
|
if (entry.password.isEmpty()) {
|
||||||
crypto_password_show.visibility = View.GONE
|
crypto_password_show.visibility = View.GONE
|
||||||
crypto_password_show_label.visibility = View.GONE
|
crypto_password_show_label.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
crypto_password_show.visibility = View.VISIBLE
|
crypto_password_show.visibility = View.VISIBLE
|
||||||
crypto_password_show_label.visibility = View.VISIBLE
|
crypto_password_show_label.visibility = View.VISIBLE
|
||||||
|
crypto_password_show.typeface = monoTypeface
|
||||||
|
crypto_password_show.text = entry.password
|
||||||
|
}
|
||||||
crypto_password_show.typeface = monoTypeface
|
crypto_password_show.typeface = monoTypeface
|
||||||
crypto_password_show.text = entry.password
|
crypto_password_show.text = entry.password
|
||||||
}
|
|
||||||
crypto_password_show.typeface = monoTypeface
|
|
||||||
crypto_password_show.text = entry.password
|
|
||||||
|
|
||||||
crypto_password_toggle_show.visibility = if (showPassword) View.GONE else View.VISIBLE
|
crypto_password_toggle_show.visibility = if (showPassword) View.GONE else View.VISIBLE
|
||||||
crypto_password_show.transformationMethod = if (showPassword) {
|
crypto_password_show.transformationMethod = if (showPassword) {
|
||||||
null
|
null
|
||||||
} else {
|
|
||||||
HoldToShowPasswordTransformation(
|
|
||||||
crypto_password_toggle_show,
|
|
||||||
Runnable { crypto_password_show.text = entry.password }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.hasExtraContent()) {
|
|
||||||
crypto_extra_show.typeface = monoTypeface
|
|
||||||
crypto_extra_show.text = entry.extraContent
|
|
||||||
|
|
||||||
if (showExtraContent) {
|
|
||||||
crypto_extra_show_layout.visibility = View.VISIBLE
|
|
||||||
crypto_extra_toggle_show.visibility = View.GONE
|
|
||||||
crypto_extra_show.transformationMethod = null
|
|
||||||
} else {
|
} else {
|
||||||
crypto_extra_show_layout.visibility = View.GONE
|
HoldToShowPasswordTransformation(
|
||||||
crypto_extra_toggle_show.visibility = View.VISIBLE
|
crypto_password_toggle_show,
|
||||||
crypto_extra_toggle_show.setOnCheckedChangeListener { _, _ ->
|
Runnable { crypto_password_show.text = entry.password }
|
||||||
crypto_extra_show.text = entry.extraContent
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto_extra_show.transformationMethod = object : PasswordTransformationMethod() {
|
if (entry.hasExtraContent()) {
|
||||||
override fun getTransformation(source: CharSequence, view: View): CharSequence {
|
crypto_extra_show.typeface = monoTypeface
|
||||||
return if (crypto_extra_toggle_show.isChecked) source else super.getTransformation(source, view)
|
crypto_extra_show.text = entry.extraContent
|
||||||
|
|
||||||
|
if (showExtraContent) {
|
||||||
|
crypto_extra_show_layout.visibility = View.VISIBLE
|
||||||
|
crypto_extra_toggle_show.visibility = View.GONE
|
||||||
|
crypto_extra_show.transformationMethod = null
|
||||||
|
} else {
|
||||||
|
crypto_extra_show_layout.visibility = View.GONE
|
||||||
|
crypto_extra_toggle_show.visibility = View.VISIBLE
|
||||||
|
crypto_extra_toggle_show.setOnCheckedChangeListener { _, _ ->
|
||||||
|
crypto_extra_show.text = entry.extraContent
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_extra_show.transformationMethod = object : PasswordTransformationMethod() {
|
||||||
|
override fun getTransformation(source: CharSequence, view: View): CharSequence {
|
||||||
|
return if (crypto_extra_toggle_show.isChecked) source else super.getTransformation(source, view)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry.hasUsername()) {
|
||||||
|
crypto_username_show.visibility = View.VISIBLE
|
||||||
|
crypto_username_show_label.visibility = View.VISIBLE
|
||||||
|
crypto_copy_username.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
crypto_copy_username.setOnClickListener { copyUsernameToClipBoard(entry.username!!) }
|
||||||
|
crypto_username_show.typeface = monoTypeface
|
||||||
|
crypto_username_show.text = entry.username
|
||||||
|
} else {
|
||||||
|
crypto_username_show.visibility = View.GONE
|
||||||
|
crypto_username_show_label.visibility = View.GONE
|
||||||
|
crypto_copy_username.visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.hasUsername()) {
|
if (entry.hasTotp() || entry.hasHotp()) {
|
||||||
crypto_username_show.visibility = View.VISIBLE
|
crypto_extra_show_layout.visibility = View.VISIBLE
|
||||||
crypto_username_show_label.visibility = View.VISIBLE
|
crypto_extra_show.typeface = monoTypeface
|
||||||
crypto_copy_username.visibility = View.VISIBLE
|
crypto_extra_show.text = entry.extraContent
|
||||||
|
|
||||||
crypto_copy_username.setOnClickListener { copyUsernameToClipBoard(entry.username!!) }
|
crypto_otp_show.visibility = View.VISIBLE
|
||||||
crypto_username_show.typeface = monoTypeface
|
crypto_otp_show_label.visibility = View.VISIBLE
|
||||||
crypto_username_show.text = entry.username
|
crypto_copy_otp.visibility = View.VISIBLE
|
||||||
} else {
|
|
||||||
crypto_username_show.visibility = View.GONE
|
|
||||||
crypto_username_show_label.visibility = View.GONE
|
|
||||||
crypto_copy_username.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.hasTotp() || entry.hasHotp()) {
|
if (entry.hasTotp()) {
|
||||||
crypto_extra_show_layout.visibility = View.VISIBLE
|
crypto_copy_otp.setOnClickListener {
|
||||||
crypto_extra_show.typeface = monoTypeface
|
copyOtpToClipBoard(
|
||||||
crypto_extra_show.text = entry.extraContent
|
Otp.calculateCode(
|
||||||
|
entry.totpSecret,
|
||||||
crypto_otp_show.visibility = View.VISIBLE
|
Date().time / (1000 * entry.totpPeriod),
|
||||||
crypto_otp_show_label.visibility = View.VISIBLE
|
entry.totpAlgorithm,
|
||||||
crypto_copy_otp.visibility = View.VISIBLE
|
entry.digits)
|
||||||
|
)
|
||||||
if (entry.hasTotp()) {
|
}
|
||||||
crypto_copy_otp.setOnClickListener {
|
crypto_otp_show.text =
|
||||||
copyOtpToClipBoard(
|
|
||||||
Otp.calculateCode(
|
Otp.calculateCode(
|
||||||
entry.totpSecret,
|
entry.totpSecret,
|
||||||
Date().time / (1000 * entry.totpPeriod),
|
Date().time / (1000 * entry.totpPeriod),
|
||||||
entry.totpAlgorithm,
|
entry.totpAlgorithm,
|
||||||
entry.digits)
|
entry.digits)
|
||||||
)
|
} else {
|
||||||
}
|
// we only want to calculate and show HOTP if the user requests it
|
||||||
crypto_otp_show.text =
|
crypto_copy_otp.setOnClickListener {
|
||||||
Otp.calculateCode(
|
if (settings.getBoolean("hotp_remember_check", false)) {
|
||||||
entry.totpSecret,
|
if (settings.getBoolean("hotp_remember_choice", false)) {
|
||||||
Date().time / (1000 * entry.totpPeriod),
|
calculateAndCommitHotp(entry)
|
||||||
entry.totpAlgorithm,
|
} else {
|
||||||
entry.digits)
|
calculateHotp(entry)
|
||||||
} else {
|
}
|
||||||
// we only want to calculate and show HOTP if the user requests it
|
|
||||||
crypto_copy_otp.setOnClickListener {
|
|
||||||
if (settings.getBoolean("hotp_remember_check", false)) {
|
|
||||||
if (settings.getBoolean("hotp_remember_choice", false)) {
|
|
||||||
calculateAndCommitHotp(entry)
|
|
||||||
} else {
|
} else {
|
||||||
calculateHotp(entry)
|
// show a dialog asking permission to update the HOTP counter in the entry
|
||||||
}
|
val checkInflater = LayoutInflater.from(this@PgpActivity)
|
||||||
} else {
|
val checkLayout = checkInflater.inflate(R.layout.otp_confirm_layout, null)
|
||||||
// show a dialog asking permission to update the HOTP counter in the entry
|
val rememberCheck: CheckBox =
|
||||||
val checkInflater = LayoutInflater.from(this)
|
checkLayout.findViewById(R.id.hotp_remember_checkbox)
|
||||||
val checkLayout = checkInflater.inflate(R.layout.otp_confirm_layout, null)
|
val dialogBuilder = MaterialAlertDialogBuilder(this@PgpActivity)
|
||||||
val rememberCheck: CheckBox =
|
dialogBuilder.setView(checkLayout)
|
||||||
checkLayout.findViewById(R.id.hotp_remember_checkbox)
|
dialogBuilder.setMessage(R.string.dialog_update_body)
|
||||||
val dialogBuilder = MaterialAlertDialogBuilder(this)
|
.setCancelable(false)
|
||||||
dialogBuilder.setView(checkLayout)
|
.setPositiveButton(R.string.dialog_update_positive) { _, _ ->
|
||||||
dialogBuilder.setMessage(R.string.dialog_update_body)
|
run {
|
||||||
.setCancelable(false)
|
calculateAndCommitHotp(entry)
|
||||||
.setPositiveButton(R.string.dialog_update_positive) { _, _ ->
|
if (rememberCheck.isChecked) {
|
||||||
run {
|
val editor = settings.edit()
|
||||||
calculateAndCommitHotp(entry)
|
editor.putBoolean("hotp_remember_check", true)
|
||||||
if (rememberCheck.isChecked) {
|
editor.putBoolean("hotp_remember_choice", true)
|
||||||
|
editor.apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.dialog_update_negative) { _, _ ->
|
||||||
|
run {
|
||||||
|
calculateHotp(entry)
|
||||||
val editor = settings.edit()
|
val editor = settings.edit()
|
||||||
editor.putBoolean("hotp_remember_check", true)
|
editor.putBoolean("hotp_remember_check", true)
|
||||||
editor.putBoolean("hotp_remember_choice", true)
|
editor.putBoolean("hotp_remember_choice", false)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
val updateDialog = dialogBuilder.create()
|
||||||
.setNegativeButton(R.string.dialog_update_negative) { _, _ ->
|
updateDialog.setTitle(R.string.dialog_update_title)
|
||||||
run {
|
updateDialog.show()
|
||||||
calculateHotp(entry)
|
}
|
||||||
val editor = settings.edit()
|
|
||||||
editor.putBoolean("hotp_remember_check", true)
|
|
||||||
editor.putBoolean("hotp_remember_choice", false)
|
|
||||||
editor.apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val updateDialog = dialogBuilder.create()
|
|
||||||
updateDialog.setTitle(R.string.dialog_update_title)
|
|
||||||
updateDialog.show()
|
|
||||||
}
|
}
|
||||||
|
crypto_otp_show.setText(R.string.hotp_pending)
|
||||||
}
|
}
|
||||||
crypto_otp_show.setText(R.string.hotp_pending)
|
crypto_otp_show.typeface = monoTypeface
|
||||||
|
} else {
|
||||||
|
crypto_otp_show.visibility = View.GONE
|
||||||
|
crypto_otp_show_label.visibility = View.GONE
|
||||||
|
crypto_copy_otp.visibility = View.GONE
|
||||||
}
|
}
|
||||||
crypto_otp_show.typeface = monoTypeface
|
|
||||||
} else {
|
|
||||||
crypto_otp_show.visibility = View.GONE
|
|
||||||
crypto_otp_show_label.visibility = View.GONE
|
|
||||||
crypto_copy_otp.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.getBoolean("copy_on_decrypt", true)) {
|
if (settings.getBoolean("copy_on_decrypt", true)) {
|
||||||
copyPasswordToClipBoard()
|
copyPasswordToClipBoard()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "An Exception occurred", e)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "An Exception occurred", e)
|
|
||||||
}
|
}
|
||||||
|
RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_DECRYPT)
|
||||||
|
RESULT_CODE_ERROR -> handleError(result)
|
||||||
}
|
}
|
||||||
RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_DECRYPT)
|
|
||||||
RESULT_CODE_ERROR -> handleError(result)
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -450,34 +452,36 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
|
|||||||
|
|
||||||
val path = if (intent.getBooleanExtra("fromDecrypt", false)) fullPath else "$fullPath/$editName.gpg"
|
val path = if (intent.getBooleanExtra("fromDecrypt", false)) fullPath else "$fullPath/$editName.gpg"
|
||||||
|
|
||||||
api?.executeApiAsync(data, iStream, oStream) { result: Intent? ->
|
api?.executeApiAsync(data, iStream, oStream, object : OpenPgpApi.IOpenPgpCallback {
|
||||||
when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) {
|
override fun onReturn(result: Intent?) {
|
||||||
RESULT_CODE_SUCCESS -> {
|
when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) {
|
||||||
try {
|
RESULT_CODE_SUCCESS -> {
|
||||||
// TODO This might fail, we should check that the write is successful
|
try {
|
||||||
val outputStream = FileUtils.openOutputStream(File(path))
|
// TODO This might fail, we should check that the write is successful
|
||||||
outputStream.write(oStream.toByteArray())
|
val outputStream = FileUtils.openOutputStream(File(path))
|
||||||
outputStream.close()
|
outputStream.write(oStream.toByteArray())
|
||||||
|
outputStream.close()
|
||||||
|
|
||||||
val returnIntent = Intent()
|
val returnIntent = Intent()
|
||||||
returnIntent.putExtra("CREATED_FILE", path)
|
returnIntent.putExtra("CREATED_FILE", path)
|
||||||
returnIntent.putExtra("NAME", editName)
|
returnIntent.putExtra("NAME", editName)
|
||||||
returnIntent.putExtra("LONG_NAME", getLongName(fullPath, repoPath, this.editName!!))
|
returnIntent.putExtra("LONG_NAME", getLongName(fullPath, repoPath, editName!!))
|
||||||
|
|
||||||
// if coming from decrypt screen->edit button
|
// if coming from decrypt screen->edit button
|
||||||
if (intent.getBooleanExtra("fromDecrypt", false)) {
|
if (intent.getBooleanExtra("fromDecrypt", false)) {
|
||||||
returnIntent.putExtra("OPERATION", "EDIT")
|
returnIntent.putExtra("OPERATION", "EDIT")
|
||||||
returnIntent.putExtra("needCommit", true)
|
returnIntent.putExtra("needCommit", true)
|
||||||
|
}
|
||||||
|
setResult(RESULT_OK, returnIntent)
|
||||||
|
finish()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "An Exception occurred", e)
|
||||||
}
|
}
|
||||||
setResult(RESULT_OK, returnIntent)
|
|
||||||
finish()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "An Exception occurred", e)
|
|
||||||
}
|
}
|
||||||
|
RESULT_CODE_ERROR -> handleError(result)
|
||||||
}
|
}
|
||||||
RESULT_CODE_ERROR -> handleError(result)
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -553,29 +557,31 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
|
|||||||
private fun getKeyIds(receivedIntent: Intent? = null) {
|
private fun getKeyIds(receivedIntent: Intent? = null) {
|
||||||
val data = receivedIntent ?: Intent()
|
val data = receivedIntent ?: Intent()
|
||||||
data.action = OpenPgpApi.ACTION_GET_KEY_IDS
|
data.action = OpenPgpApi.ACTION_GET_KEY_IDS
|
||||||
api?.executeApiAsync(data, null, null) { result: Intent? ->
|
api?.executeApiAsync(data, null, null, object : OpenPgpApi.IOpenPgpCallback {
|
||||||
when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) {
|
override fun onReturn(result: Intent?) {
|
||||||
RESULT_CODE_SUCCESS -> {
|
when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) {
|
||||||
try {
|
RESULT_CODE_SUCCESS -> {
|
||||||
val ids = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS)
|
try {
|
||||||
?: LongArray(0)
|
val ids = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS)
|
||||||
val keys = ids.map { it.toString() }.toSet()
|
?: LongArray(0)
|
||||||
|
val keys = ids.map { it.toString() }.toSet()
|
||||||
|
|
||||||
// use Long
|
// use Long
|
||||||
settings.edit().putStringSet("openpgp_key_ids_set", keys).apply()
|
settings.edit().putStringSet("openpgp_key_ids_set", keys).apply()
|
||||||
|
|
||||||
showSnackbar("PGP keys selected")
|
showSnackbar("PGP keys selected")
|
||||||
|
|
||||||
setResult(RESULT_OK)
|
setResult(RESULT_OK)
|
||||||
finish()
|
finish()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "An Exception occurred", e)
|
Log.e(TAG, "An Exception occurred", e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_KEY_ID)
|
||||||
|
RESULT_CODE_ERROR -> handleError(result)
|
||||||
}
|
}
|
||||||
RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_KEY_ID)
|
|
||||||
RESULT_CODE_ERROR -> handleError(result)
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Exception?) {}
|
override fun onError(e: Exception?) {}
|
||||||
|
@@ -40,7 +40,7 @@
|
|||||||
</androidx.preference.PreferenceCategory>
|
</androidx.preference.PreferenceCategory>
|
||||||
|
|
||||||
<androidx.preference.PreferenceCategory android:title="@string/pref_crypto_title">
|
<androidx.preference.PreferenceCategory android:title="@string/pref_crypto_title">
|
||||||
<org.openintents.openpgp.util.OpenPgpAppPreference2
|
<me.msfjarvis.openpgpktx.preference.OpenPgpAppPreference
|
||||||
android:key="openpgp_provider_list"
|
android:key="openpgp_provider_list"
|
||||||
android:title="@string/pref_provider_title" />
|
android:title="@string/pref_provider_title" />
|
||||||
<androidx.preference.Preference
|
<androidx.preference.Preference
|
||||||
|
@@ -2,4 +2,4 @@
|
|||||||
* Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved.
|
* Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved.
|
||||||
* SPDX-License-Identifier: GPL-3.0-only
|
* SPDX-License-Identifier: GPL-3.0-only
|
||||||
*/
|
*/
|
||||||
include(":app")
|
include ':app'
|
||||||
|
@@ -35,7 +35,7 @@ ext {
|
|||||||
commons_codec: '1.13',
|
commons_codec: '1.13',
|
||||||
jgit: '3.7.1.201504261725-r',
|
jgit: '3.7.1.201504261725-r',
|
||||||
jsch: '0.1.55',
|
jsch: '0.1.55',
|
||||||
openpgp: 'v14',
|
openpgp: '0.1.0',
|
||||||
sshauth: '1.0'
|
sshauth: '1.0'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user