diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index da1536d..e1a40ea 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ @@ -21,32 +20,28 @@ + android:name=".pluginSDK.PluginAccessBroadcastReceiver" + android:exported="true"> + + android:exported="true"> + - - - - - - + + + - \ No newline at end of file diff --git a/app/src/main/java/net/helcel/fidelity/activity/MainActivity.kt b/app/src/main/java/net/helcel/fidelity/activity/MainActivity.kt index 9f1cad3..065b366 100644 --- a/app/src/main/java/net/helcel/fidelity/activity/MainActivity.kt +++ b/app/src/main/java/net/helcel/fidelity/activity/MainActivity.kt @@ -18,6 +18,7 @@ class MainActivity : AppCompatActivity() { private lateinit var binding: ActMainBinding private lateinit var sharedPreferences: SharedPreferences + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) sharedPreferences = diff --git a/app/src/main/java/net/helcel/fidelity/activity/fragment/CreateEntry.kt b/app/src/main/java/net/helcel/fidelity/activity/fragment/CreateEntry.kt index e77d6b1..8d53636 100644 --- a/app/src/main/java/net/helcel/fidelity/activity/fragment/CreateEntry.kt +++ b/app/src/main/java/net/helcel/fidelity/activity/fragment/CreateEntry.kt @@ -26,7 +26,7 @@ class CreateEntry : Fragment() { private val handler = Handler(Looper.getMainLooper()) private lateinit var binding: FragCreateEntryBinding - private val resultLauncherAdd = KeepassWrapper.resultLauncherAdd(this) { + private val resultLauncherAdd = KeepassWrapper.resultLauncher(this) { val r = KeepassWrapper.entryExtract(it) if (!KeepassWrapper.isProtected(it)) { CacheManager.addFidelity(r) diff --git a/app/src/main/java/net/helcel/fidelity/activity/fragment/Launcher.kt b/app/src/main/java/net/helcel/fidelity/activity/fragment/Launcher.kt index 89e793d..21fd1a1 100644 --- a/app/src/main/java/net/helcel/fidelity/activity/fragment/Launcher.kt +++ b/app/src/main/java/net/helcel/fidelity/activity/fragment/Launcher.kt @@ -23,7 +23,7 @@ class Launcher : Fragment() { private lateinit var binding: FragLauncherBinding private lateinit var fidelityListAdapter: FidelityListAdapter - private val resultLauncherQuery = KeepassWrapper.resultLauncherQuery(this) { + private val resultLauncherQuery = KeepassWrapper.resultLauncher(this) { val r = KeepassWrapper.entryExtract(it) if (!KeepassWrapper.isProtected(it)) { CacheManager.addFidelity(r) @@ -80,7 +80,7 @@ class Launcher : Fragment() { private fun startGetFromKeepass() { try { - this.resultLauncherQuery.launch(Kp2aControl.queryEntryIntentForOwnPackage) + this.resultLauncherQuery.launch(Kp2aControl.getQueryEntryForOwnPackageIntent()) } catch (e: ActivityNotFoundException) { ErrorToaster.noKP2AFound(requireActivity()) } diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/AccessManager.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/AccessManager.kt index 2ab93f0..416276e 100644 --- a/app/src/main/java/net/helcel/fidelity/pluginSDK/AccessManager.kt +++ b/app/src/main/java/net/helcel/fidelity/pluginSDK/AccessManager.kt @@ -2,141 +2,87 @@ package net.helcel.fidelity.pluginSDK import android.content.Context import android.content.SharedPreferences -import android.content.pm.PackageManager -import android.text.TextUtils -import android.util.Log import org.json.JSONArray import org.json.JSONException + +class PluginAccessException(msg: String) : Exception(msg) + + object AccessManager { - private const val _tag = "Kp2aPluginSDK" private const val PREF_KEY_SCOPE = "scope" private const val PREF_KEY_TOKEN = "token" private fun stringArrayToString(values: ArrayList): String? { + if (values.isEmpty()) return null val a = JSONArray() - for (i in values.indices) { - a.put(values[i]) - } - return if (values.isNotEmpty()) { - a.toString() - } else { - null - } + values.forEach { a.put(it) } + return a.toString() } private fun stringToStringArray(s: String?): ArrayList { val strings = ArrayList() - if (!TextUtils.isEmpty(s)) { - try { - val a = JSONArray(s) - for (i in 0 until a.length()) { - val url = a.optString(i) - strings.add(url) - } - } catch (e: JSONException) { - e.printStackTrace() - } + if (s.isNullOrEmpty()) return strings + + try { + val a = JSONArray(s) + for (i in 0 until a.length()) + strings.add(a.optString(i)) + } catch (e: JSONException) { + e.printStackTrace() } return strings } fun storeAccessToken( ctx: Context, - hostPackage: String, - accessToken: String, + hostPackage: String?, + accessToken: String?, scopes: ArrayList ) { val prefs = getPrefsForHost(ctx, hostPackage) - val edit = prefs.edit() edit.putString(PREF_KEY_TOKEN, accessToken) val scopesString = stringArrayToString(scopes) edit.putString(PREF_KEY_SCOPE, scopesString) edit.apply() - Log.d( - _tag, - "stored access token " + accessToken.substring( - 0, - 4 - ) + "... for " + scopes.size + " scopes (" + scopesString + ")." - ) val hostPrefs = ctx.getSharedPreferences("KP2A.PluginAccess.hosts", Context.MODE_PRIVATE) - if (!hostPrefs.contains(hostPackage)) { + if (!hostPrefs.contains(hostPackage)) hostPrefs.edit().putString(hostPackage, "").apply() - } - } - - fun preparePopup(popupMenu: Any) { - try { - val fields = popupMenu.javaClass.declaredFields - for (field in fields) { - if ("mPopup" == field.name) { - field.isAccessible = true - val menuPopupHelper = field[popupMenu] - val classPopupHelper = Class.forName( - menuPopupHelper - .javaClass.name - ) - val setForceIcons = classPopupHelper.getMethod( - "setForceShowIcon", Boolean::class.javaPrimitiveType - ) - setForceIcons.invoke(menuPopupHelper, true) - break - } - } - } catch (e: Exception) { - e.printStackTrace() - } } private fun getPrefsForHost( ctx: Context, - hostPackage: String + hostPackage: String? ): SharedPreferences { - val prefs = ctx.getSharedPreferences("KP2A.PluginAccess.$hostPackage", Context.MODE_PRIVATE) - return prefs + return ctx.getSharedPreferences("KP2A.PluginAccess.$hostPackage", Context.MODE_PRIVATE) } - fun tryGetAccessToken(ctx: Context, hostPackage: String, scopes: ArrayList): String? { - if (TextUtils.isEmpty(hostPackage)) { - Log.d(_tag, "hostPackage is empty!") - return null - } - Log.d(_tag, "trying to find prefs for $hostPackage") + fun tryGetAccessToken(ctx: Context, hostPackage: String?, scopes: ArrayList): String? { + if (hostPackage.isNullOrEmpty()) return null + val prefs = getPrefsForHost(ctx, hostPackage) val scopesString = prefs.getString(PREF_KEY_SCOPE, "") - Log.d(_tag, "available scopes: $scopesString") val currentScope = stringToStringArray(scopesString) - if (isSubset(scopes, currentScope)) { - return prefs.getString(PREF_KEY_TOKEN, null) - } else { - Log.d(_tag, "looks like scope changed. Access token invalid.") + if (!isSubset(scopes, currentScope)) return null - } + return prefs.getString(PREF_KEY_TOKEN, null) + } private fun isSubset( requiredScopes: ArrayList, availableScopes: ArrayList ): Boolean { - for (r in requiredScopes) { - if (availableScopes.indexOf(r) < 0) { - Log.d(_tag, "Scope " + r + " not available. " + availableScopes.size) - return false - } - } - return true + return availableScopes.containsAll(requiredScopes) } fun removeAccessToken( - ctx: Context, hostPackage: String, - accessToken: String + ctx: Context, hostPackage: String?, + accessToken: String? ) { val prefs = getPrefsForHost(ctx, hostPackage) - - Log.d(_tag, "removing AccessToken.") if (prefs.getString(PREF_KEY_TOKEN, "") == accessToken) { val edit = prefs.edit() edit.clear() @@ -149,31 +95,11 @@ object AccessManager { } } - fun getAllHostPackages(ctx: Context): Set { - val prefs = ctx.getSharedPreferences("KP2A.PluginAccess.hosts", Context.MODE_PRIVATE) - val result: MutableSet = HashSet() - for (host in prefs.all.keys) { - try { - val info = ctx.packageManager.getPackageInfo(host, PackageManager.GET_META_DATA) - //if we get here, the package is still there - result.add(host) - } catch (e: PackageManager.NameNotFoundException) { - //host gone. ignore. - } - } - return result - } - - - /** - * Returns a valid access token or throws PluginAccessException - */ fun getAccessToken( - context: Context, hostPackage: String, + context: Context, hostPackage: String?, scopes: ArrayList ): String { - val accessToken = tryGetAccessToken(context, hostPackage, scopes) - ?: throw PluginAccessException(hostPackage, scopes) - return accessToken + return tryGetAccessToken(context, hostPackage, scopes) + ?: throw PluginAccessException(hostPackage + scopes) } } diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/KeepassDef.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/KeepassDef.kt new file mode 100644 index 0000000..58d5337 --- /dev/null +++ b/app/src/main/java/net/helcel/fidelity/pluginSDK/KeepassDef.kt @@ -0,0 +1,9 @@ +package net.helcel.fidelity.pluginSDK + +object KeepassDef { + var TitleField: String = "Title" + var UserNameField: String = "UserName" + var PasswordField: String = "Password" + var UrlField: String = "URL" + var NotesField: String = "Notes" +} diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/KeepassDefs.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/KeepassDefs.kt deleted file mode 100644 index 7a0ea22..0000000 --- a/app/src/main/java/net/helcel/fidelity/pluginSDK/KeepassDefs.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.helcel.fidelity.pluginSDK - -object KeepassDefs { - /// - /// Default identifier string for the title field. Should not contain - /// spaces, tabs or other whitespace. - /// - var TitleField: String = "Title" - - /// - /// Default identifier string for the user name field. Should not contain - /// spaces, tabs or other whitespace. - /// - private var UserNameField: String = "UserName" - - /// - /// Default identifier string for the password field. Should not contain - /// spaces, tabs or other whitespace. - /// - private var PasswordField: String = "Password" - - /// - /// Default identifier string for the URL field. Should not contain - /// spaces, tabs or other whitespace. - /// - var UrlField: String = "URL" - - /// - /// Default identifier string for the notes field. Should not contain - /// spaces, tabs or other whitespace. - /// - private var NotesField: String = "Notes" - - - fun IsStandardField(strFieldName: String?): Boolean { - if (strFieldName == null) return false - if (strFieldName == TitleField) return true - if (strFieldName == UserNameField) return true - if (strFieldName == PasswordField) return true - if (strFieldName == UrlField) return true - if (strFieldName == NotesField) return true - - return false - } -} diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/Kp2aControl.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/Kp2aControl.kt index 54d2bfd..0fbbe3e 100644 --- a/app/src/main/java/net/helcel/fidelity/pluginSDK/Kp2aControl.kt +++ b/app/src/main/java/net/helcel/fidelity/pluginSDK/Kp2aControl.kt @@ -1,96 +1,38 @@ package net.helcel.fidelity.pluginSDK import android.content.Intent -import android.text.TextUtils import org.json.JSONException import org.json.JSONObject object Kp2aControl { - /** - * Creates and returns an intent to launch Keepass2Android for adding an entry with the given fields. - * @param fields Key/Value pairs of the field values. See KeepassDefs for standard keys. - * @param protectedFields List of keys of the protected fields. - * @return Intent to start Keepass2Android. - * @throws JSONException - */ - fun getAddEntryIntent( - fields: HashMap?, - protectedFields: ArrayList? - ): Intent { - return getAddEntryIntent(JSONObject((fields as Map<*, *>?)!!).toString(), protectedFields) - } - private fun getAddEntryIntent( - outputData: String?, + fun getAddEntryIntent( + fields: HashMap, protectedFields: ArrayList? ): Intent { + val outputData = JSONObject((fields as Map<*, *>)).toString() val startKp2aIntent = Intent(Strings.ACTION_START_WITH_TASK) startKp2aIntent.addCategory(Intent.CATEGORY_DEFAULT) startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) startKp2aIntent.putExtra("KP2A_APPTASK", "CreateEntryThenCloseTask") - startKp2aIntent.putExtra("ShowUserNotifications", "false") //KP2A expects a StringExtra + startKp2aIntent.putExtra("ShowUserNotifications", "false") startKp2aIntent.putExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA, outputData) - if (protectedFields != null) startKp2aIntent.putStringArrayListExtra( - Strings.EXTRA_PROTECTED_FIELDS_LIST, - protectedFields - ) - - + if (protectedFields != null) + startKp2aIntent.putStringArrayListExtra( + Strings.EXTRA_PROTECTED_FIELDS_LIST, + protectedFields + ) return startKp2aIntent } - - /** - * Creates an intent to open a Password Entry matching searchText - * @param searchText queryString - * @param showUserNotifications if true, the notifications (copy to clipboard, keyboard) are displayed - * @param closeAfterOpen if true, the entry is opened and KP2A is immediately closed - * @return Intent to start KP2A with - */ - fun getOpenEntryIntent( - searchText: String?, - showUserNotifications: Boolean, - closeAfterOpen: Boolean - ): Intent { - val startKp2aIntent = Intent(Strings.ACTION_START_WITH_TASK) - startKp2aIntent.addCategory(Intent.CATEGORY_DEFAULT) - startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) - startKp2aIntent.putExtra("KP2A_APPTASK", "SearchUrlTask") - startKp2aIntent.putExtra("ShowUserNotifications", showUserNotifications.toString()) - startKp2aIntent.putExtra("CloseAfterCreate", closeAfterOpen.toString()) - startKp2aIntent.putExtra("UrlToSearch", searchText) - return startKp2aIntent + fun getQueryEntryForOwnPackageIntent(): Intent { + return Intent(Strings.ACTION_QUERY_CREDENTIALS_FOR_OWN_PACKAGE) } - /** - * Creates an intent to query a password entry from KP2A. The credentials are returned as Activity result. - * @param searchText Text to search for. Should be a URL or "androidapp://com.my.package." - * @return an Intent to start KP2A with - */ - fun getQueryEntryIntent(searchText: String?): Intent { - val i = Intent(Strings.ACTION_QUERY_CREDENTIALS) - if (!TextUtils.isEmpty(searchText)) i.putExtra(Strings.EXTRA_QUERY_STRING, searchText) - return i - } - - val queryEntryIntentForOwnPackage: Intent - /** - * Creates an intent to query a password entry from KP2A, matching to the current app's package . - * The credentials are returned as Activity result. - * This requires SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE. - * @return an Intent to start KP2A with - */ - get() = Intent(Strings.ACTION_QUERY_CREDENTIALS_FOR_OWN_PACKAGE) - - /** - * Converts the entry fields returned in an intent from a query to a hashmap. - * @param intent data received in onActivityResult after getQueryEntryIntent(ForOwnPackage) - * @return HashMap with keys = field names (see KeepassDefs for standard keys) and values = values - */ - fun getEntryFieldsFromIntent(intent: Intent): HashMap { + fun getEntryFieldsFromIntent(intent: Intent?): HashMap { val res = HashMap() try { - val json = JSONObject(intent.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA)!!) + val json = JSONObject(intent?.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA)!!) val iter = json.keys() while (iter.hasNext()) { val key = iter.next() diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessBroadcastReceiver.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessBroadcastReceiver.kt index 97a1d2b..097f4a5 100644 --- a/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessBroadcastReceiver.kt +++ b/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessBroadcastReceiver.kt @@ -3,55 +3,29 @@ package net.helcel.fidelity.pluginSDK import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.util.Log -/** - * Broadcast flow between Host and Plugin - * ====================================== - * - * The host is responsible for deciding when to initiate the session. It - * should initiate the session as soon as plugins are required or when a plugin - * has been updated through the OS. - * It will then send a broadcast to request the currently required scope. - * The plugin then sends a broadcast to the app which scope is required. If an - * access token is already available, it's sent along with the requset. - * - * If a previous permission has been revoked (or the app settings cleared or the - * permissions have been extended or the token is invalid for any other reason) - * the host will answer with a Revoked-Permission broadcast (i.e. the plugin is - * unconnected.) - * - * Unconnected plugins must be permitted by the user (requiring user action). - * When the user grants access, the plugin will receive an access token for - * the host. This access token is valid for the requested scope. If the scope - * changes (e.g after an update of the plugin), the access token becomes invalid. - * - */ -abstract class PluginAccessBroadcastReceiver : BroadcastReceiver() { +class PluginAccessBroadcastReceiver : BroadcastReceiver() { override fun onReceive(ctx: Context, intent: Intent) { - val action = intent.action - Log.d(_tag, "received broadcast with action=$action") - if (action == null) return + val action = intent.action ?: return when (action) { Strings.ACTION_TRIGGER_REQUEST_ACCESS -> requestAccess(ctx, intent) Strings.ACTION_RECEIVE_ACCESS -> receiveAccess(ctx, intent) Strings.ACTION_REVOKE_ACCESS -> revokeAccess(ctx, intent) - else -> {} + else -> println(action) } } - private fun revokeAccess(ctx: Context, intent: Intent) { val senderPackage = intent.getStringExtra(Strings.EXTRA_SENDER) val accessToken = intent.getStringExtra(Strings.EXTRA_ACCESS_TOKEN) - AccessManager.removeAccessToken(ctx, senderPackage!!, accessToken!!) + AccessManager.removeAccessToken(ctx, senderPackage, accessToken) } private fun receiveAccess(ctx: Context, intent: Intent) { val senderPackage = intent.getStringExtra(Strings.EXTRA_SENDER) val accessToken = intent.getStringExtra(Strings.EXTRA_ACCESS_TOKEN) - AccessManager.storeAccessToken(ctx, senderPackage!!, accessToken!!, scopes) + AccessManager.storeAccessToken(ctx, senderPackage, accessToken, scopes) } private fun requestAccess(ctx: Context, intent: Intent) { @@ -62,21 +36,18 @@ abstract class PluginAccessBroadcastReceiver : BroadcastReceiver() { rpi.putExtra(Strings.EXTRA_SENDER, ctx.packageName) rpi.putExtra(Strings.EXTRA_REQUEST_TOKEN, requestToken) - val token: String? = AccessManager.tryGetAccessToken(ctx, senderPackage!!, scopes) + val token: String? = AccessManager.tryGetAccessToken(ctx, senderPackage, scopes) rpi.putExtra(Strings.EXTRA_ACCESS_TOKEN, token) rpi.putStringArrayListExtra(Strings.EXTRA_SCOPES, scopes) - Log.d(_tag, "requesting access for " + scopes.size + " tokens.") ctx.sendBroadcast(rpi) } - /** - * - * @return the list of required scopes for this plugin. - */ - abstract val scopes: ArrayList - - companion object { - private const val _tag = "Kp2aPluginSDK" - } + private val scopes: ArrayList = ArrayList( + listOf( + Strings.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE, + Strings.SCOPE_DATABASE_ACTIONS, + Strings.SCOPE_CURRENT_ENTRY, + ) + ) } diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessException.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessException.kt deleted file mode 100644 index 571b879..0000000 --- a/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessException.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.helcel.fidelity.pluginSDK - -class PluginAccessException : Exception { - constructor(what: String?) : super(what) - - constructor(hostPackage: String?, scopes: ArrayList) - - companion object { - /** - * - */ - private const val serialVersionUID = 1L - } -} diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessReceiver.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessReceiver.kt deleted file mode 100644 index 63895d6..0000000 --- a/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginAccessReceiver.kt +++ /dev/null @@ -1,16 +0,0 @@ -package net.helcel.fidelity.pluginSDK - -import kotlin.collections.ArrayList - - -class PluginAccessReceiver : PluginAccessBroadcastReceiver() { - - override val scopes: ArrayList = ArrayList() - - init { - this.scopes.add(Strings.SCOPE_DATABASE_ACTIONS) - this.scopes.add(Strings.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE) - } - -} - diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginActionBroadcastReceiver.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginActionBroadcastReceiver.kt index 9b2af63..5a7d583 100644 --- a/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginActionBroadcastReceiver.kt +++ b/app/src/main/java/net/helcel/fidelity/pluginSDK/PluginActionBroadcastReceiver.kt @@ -22,7 +22,8 @@ class PluginActionBroadcastReceiver : BroadcastReceiver() { get() { val res = HashMap() try { - val json = JSONObject(_intent.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA)!!) + val json = + JSONObject(_intent.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA) ?: "") val iter = json.keys() while (iter.hasNext()) { val key = iter.next() @@ -54,14 +55,13 @@ class PluginActionBroadcastReceiver : BroadcastReceiver() { get() = _intent.getStringExtra(Strings.EXTRA_ENTRY_ID) - @Throws(PluginAccessException::class) fun setEntryField(fieldId: String?, fieldValue: String?, isProtected: Boolean) { val i = Intent(Strings.ACTION_SET_ENTRY_FIELD) val scope = ArrayList() scope.add(Strings.SCOPE_CURRENT_ENTRY) i.putExtra( Strings.EXTRA_ACCESS_TOKEN, AccessManager.getAccessToken( - context, hostPackage!!, scope + context, hostPackage, scope ) ) i.setPackage(hostPackage) @@ -132,7 +132,6 @@ class PluginActionBroadcastReceiver : BroadcastReceiver() { */ get() = protectedFieldsListFromIntent - @Throws(PluginAccessException::class) fun addEntryAction( actionDisplayText: String?, actionIconResourceId: Int, @@ -141,7 +140,6 @@ class PluginActionBroadcastReceiver : BroadcastReceiver() { addEntryFieldAction(null, null, actionDisplayText, actionIconResourceId, actionData) } - @Throws(PluginAccessException::class) fun addEntryFieldAction( actionId: String?, fieldId: String?, @@ -191,24 +189,28 @@ class PluginActionBroadcastReceiver : BroadcastReceiver() { } override fun onReceive(ctx: Context, intent: Intent) { - val action = intent.action + val action = intent.action ?: return Log.d( "KP2A.pluginsdk", "received broadcast in PluginActionBroadcastReceiver with action=$action" ) - if (action == null) return - if (action == Strings.ACTION_OPEN_ENTRY) { - openEntry(OpenEntryAction(ctx, intent)) - } else if (action == Strings.ACTION_CLOSE_ENTRY_VIEW) { - closeEntryView(CloseEntryViewAction(ctx, intent)) - } else if (action == Strings.ACTION_ENTRY_ACTION_SELECTED) { - actionSelected(ActionSelectedAction(ctx, intent)) - } else if (action == Strings.ACTION_ENTRY_OUTPUT_MODIFIED) { - entryOutputModified(EntryOutputModifiedAction(ctx, intent)) - } else if (action == Strings.ACTION_LOCK_DATABASE || action == Strings.ACTION_UNLOCK_DATABASE || action == Strings.ACTION_OPEN_DATABASE || action == Strings.ACTION_CLOSE_DATABASE) { - dbAction(DatabaseAction(ctx, intent)) - } else { - //TODO handle unexpected action + println(action) + + when (action) { + Strings.ACTION_OPEN_ENTRY -> openEntry(OpenEntryAction(ctx, intent)) + Strings.ACTION_CLOSE_ENTRY_VIEW -> closeEntryView(CloseEntryViewAction(ctx, intent)) + Strings.ACTION_ENTRY_ACTION_SELECTED -> + actionSelected(ActionSelectedAction(ctx, intent)) + + Strings.ACTION_ENTRY_OUTPUT_MODIFIED -> + entryOutputModified(EntryOutputModifiedAction(ctx, intent)) + + Strings.ACTION_LOCK_DATABASE -> dbAction(DatabaseAction(ctx, intent)) + Strings.ACTION_UNLOCK_DATABASE -> dbAction(DatabaseAction(ctx, intent)) + Strings.ACTION_OPEN_DATABASE -> dbAction(DatabaseAction(ctx, intent)) + Strings.ACTION_CLOSE_DATABASE -> dbAction(DatabaseAction(ctx, intent)) + + else -> println(action) } } diff --git a/app/src/main/java/net/helcel/fidelity/pluginSDK/Strings.kt b/app/src/main/java/net/helcel/fidelity/pluginSDK/Strings.kt index 7b0a46e..476c861 100644 --- a/app/src/main/java/net/helcel/fidelity/pluginSDK/Strings.kt +++ b/app/src/main/java/net/helcel/fidelity/pluginSDK/Strings.kt @@ -17,11 +17,6 @@ object Strings { const val SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE = "keepass2android.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE" - /** - * Plugin may query credentials for a deliberate package - */ - const val SCOPE_QUERY_CREDENTIALS = "keepass2android.SCOPE_QUERY_CREDENTIALS" - /** * Extra key to transfer a (json serialized) list of scopes */ @@ -97,11 +92,6 @@ object Strings { */ const val EXTRA_ENTRY_ID = "keepass2android.EXTRA_ENTRY_DATA" - /** - * Json serialized data of the PwEntry (C# class) representing the opened entry. - * currently not implemented. - */ - //const val EXTRA_ENTRY_DATA = "keepass2android.EXTRA_ENTRY_DATA"; /** * Json serialized list of fields, transformed using the database context (i.e. placeholders are replaced already) @@ -157,13 +147,6 @@ object Strings { const val ACTION_QUERY_CREDENTIALS_FOR_OWN_PACKAGE = "keepass2android.ACTION_QUERY_CREDENTIALS_FOR_OWN_PACKAGE" - - /** - * Action when plugin wants to query credentials for a deliberate package - * The query string is passed as intent data - */ - const val ACTION_QUERY_CREDENTIALS = "keepass2android.ACTION_QUERY_CREDENTIALS" - /** * Action for an intent from the plugin to KP2A to set (i.e. add or update) a field in the entry. * May be used to update existing or add new fields at any time while the entry is opened. @@ -189,7 +172,5 @@ object Strings { const val EXTRA_FIELD_VALUE = "keepass2android.EXTRA_FIELD_VALUE" const val EXTRA_FIELD_PROTECTED = "keepass2android.EXTRA_FIELD_PROTECTED" - const val PREFIX_STRING = "STRING_" - const val PREFIX_BINARY = "BINARY_" } diff --git a/app/src/main/java/net/helcel/fidelity/tools/BarcodeGenerator.kt b/app/src/main/java/net/helcel/fidelity/tools/BarcodeGenerator.kt index 15e9f77..fa46e5f 100644 --- a/app/src/main/java/net/helcel/fidelity/tools/BarcodeGenerator.kt +++ b/app/src/main/java/net/helcel/fidelity/tools/BarcodeGenerator.kt @@ -19,14 +19,17 @@ object BarcodeGenerator { android.graphics.Color.WHITE } - fun generateBarcode(content: String?, f: String?, width: Int): Bitmap? { + fun generateBarcode(content: String?, f: String?, w: Int): Bitmap? { if (content.isNullOrEmpty() || f.isNullOrEmpty()) { return null } try { val format = stringToFormat(f) val writer = MultiFormatWriter() - val height = (formatToRatio(format) * width).toInt() + val height = (w * formatToRatio(format)).toInt() + val width = (w * 1.0f).toInt() + + val bitMatrix: BitMatrix = writer.encode(content, format, width, height) val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) diff --git a/app/src/main/java/net/helcel/fidelity/tools/BacodeScanner.kt b/app/src/main/java/net/helcel/fidelity/tools/BarcodeScanner.kt similarity index 100% rename from app/src/main/java/net/helcel/fidelity/tools/BacodeScanner.kt rename to app/src/main/java/net/helcel/fidelity/tools/BarcodeScanner.kt diff --git a/app/src/main/java/net/helcel/fidelity/tools/KeepassWrapper.kt b/app/src/main/java/net/helcel/fidelity/tools/KeepassWrapper.kt index 0d799e3..065eab5 100644 --- a/app/src/main/java/net/helcel/fidelity/tools/KeepassWrapper.kt +++ b/app/src/main/java/net/helcel/fidelity/tools/KeepassWrapper.kt @@ -6,7 +6,7 @@ import android.os.Bundle import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment -import net.helcel.fidelity.pluginSDK.KeepassDefs +import net.helcel.fidelity.pluginSDK.KeepassDef import net.helcel.fidelity.pluginSDK.Kp2aControl object KeepassWrapper { @@ -25,8 +25,8 @@ object KeepassWrapper { val fields = HashMap() val protected = ArrayList() - fields[KeepassDefs.TitleField] = title - fields[KeepassDefs.UrlField] = + fields[KeepassDef.TitleField] = title + fields[KeepassDef.UrlField] = "androidapp://" + fragment.requireActivity().packageName fields[CODE_FIELD] = code fields[FORMAT_FIELD] = format @@ -37,26 +37,14 @@ object KeepassWrapper { } - fun resultLauncherAdd( + fun resultLauncher( fragment: Fragment, callback: (HashMap) -> Unit ): ActivityResultLauncher { return fragment.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - println(result.toString()) - if (result.resultCode == Activity.RESULT_OK) { - val credentials = Kp2aControl.getEntryFieldsFromIntent(result.data) - println(credentials.toList().toString()) - callback(credentials) - } - } - } - - fun resultLauncherQuery( - fragment: Fragment, - callback: (HashMap) -> Unit - ): ActivityResultLauncher { - return fragment.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + println(result.resultCode) + println(result.data.toString()) if (result.resultCode == Activity.RESULT_OK) { val credentials = Kp2aControl.getEntryFieldsFromIntent(result.data) println(credentials.toList().toString()) @@ -67,7 +55,7 @@ object KeepassWrapper { fun entryExtract(map: HashMap): Triple { return Triple( - map[KeepassDefs.TitleField], + map[KeepassDef.TitleField], map[CODE_FIELD], map[FORMAT_FIELD] )