restore PluginSDK
This commit is contained in:
9
src/java/Keepass2AndroidPluginSDK/.classpath
Normal file
9
src/java/Keepass2AndroidPluginSDK/.classpath
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="gen"/>
|
||||||
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||||
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||||
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||||
|
<classpathentry kind="output" path="bin/classes"/>
|
||||||
|
</classpath>
|
||||||
33
src/java/Keepass2AndroidPluginSDK/.project
Normal file
33
src/java/Keepass2AndroidPluginSDK/.project
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>Keepass2AndroidPluginSDK</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
||||||
18
src/java/Keepass2AndroidPluginSDK/AndroidManifest.xml
Normal file
18
src/java/Keepass2AndroidPluginSDK/AndroidManifest.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="keepass2android.pluginsdk"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0" >
|
||||||
|
|
||||||
|
<uses-sdk
|
||||||
|
android:minSdkVersion="8"
|
||||||
|
android:targetSdkVersion="19" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/AppTheme" >
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
Binary file not shown.
3
src/java/Keepass2AndroidPluginSDK/lint.xml
Normal file
3
src/java/Keepass2AndroidPluginSDK/lint.xml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<lint>
|
||||||
|
</lint>
|
||||||
20
src/java/Keepass2AndroidPluginSDK/proguard-project.txt
Normal file
20
src/java/Keepass2AndroidPluginSDK/proguard-project.txt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# To enable ProGuard in your project, edit project.properties
|
||||||
|
# to define the proguard.config property as described in that file.
|
||||||
|
#
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the ProGuard
|
||||||
|
# include property in project.properties.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
15
src/java/Keepass2AndroidPluginSDK/project.properties
Normal file
15
src/java/Keepass2AndroidPluginSDK/project.properties
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system edit
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
#
|
||||||
|
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||||
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-19
|
||||||
|
android.library=true
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
11
src/java/Keepass2AndroidPluginSDK/res/values-v11/styles.xml
Normal file
11
src/java/Keepass2AndroidPluginSDK/res/values-v11/styles.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme for API 11+. This theme completely replaces
|
||||||
|
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||||
|
<!-- API 11 theme customizations can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
12
src/java/Keepass2AndroidPluginSDK/res/values-v14/styles.xml
Normal file
12
src/java/Keepass2AndroidPluginSDK/res/values-v14/styles.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme for API 14+. This theme completely replaces
|
||||||
|
AppBaseTheme from BOTH res/values/styles.xml and
|
||||||
|
res/values-v11/styles.xml on API 14+ devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
|
||||||
|
<!-- API 14 theme customizations can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Example customization of dimensions originally defined in res/values/dimens.xml
|
||||||
|
(such as screen margins) for screens with more than 820dp of available width. This
|
||||||
|
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
|
||||||
|
-->
|
||||||
|
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
7
src/java/Keepass2AndroidPluginSDK/res/values/dimens.xml
Normal file
7
src/java/Keepass2AndroidPluginSDK/res/values/dimens.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
6
src/java/Keepass2AndroidPluginSDK/res/values/strings.xml
Normal file
6
src/java/Keepass2AndroidPluginSDK/res/values/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="app_name">Keepass2Android Plugin SDK</string>
|
||||||
|
|
||||||
|
</resources>
|
||||||
20
src/java/Keepass2AndroidPluginSDK/res/values/styles.xml
Normal file
20
src/java/Keepass2AndroidPluginSDK/res/values/styles.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme, dependent on API level. This theme is replaced
|
||||||
|
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||||
|
<!--
|
||||||
|
Theme customizations available in newer API levels can go in
|
||||||
|
res/values-vXX/styles.xml, while customizations related to
|
||||||
|
backward-compatibility can go here.
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Application theme. -->
|
||||||
|
<style name="AppTheme" parent="AppBaseTheme">
|
||||||
|
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
package keepass2android.pluginsdk;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.Editor;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
|
|
||||||
|
|
||||||
|
public class AccessManager
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final String _tag = "Kp2aPluginSDK";
|
||||||
|
private static final String PREF_KEY_SCOPE = "scope";
|
||||||
|
private static final String PREF_KEY_TOKEN = "token";
|
||||||
|
|
||||||
|
public static String stringArrayToString(ArrayList<String> values) {
|
||||||
|
JSONArray a = new JSONArray();
|
||||||
|
for (int i = 0; i < values.size(); i++) {
|
||||||
|
a.put(values.get(i));
|
||||||
|
}
|
||||||
|
if (!values.isEmpty()) {
|
||||||
|
return a.toString();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<String> stringToStringArray(String s) {
|
||||||
|
ArrayList<String> strings = new ArrayList<String>();
|
||||||
|
if (TextUtils.isEmpty(s) == false) {
|
||||||
|
try {
|
||||||
|
JSONArray a = new JSONArray(s);
|
||||||
|
for (int i = 0; i < a.length(); i++) {
|
||||||
|
String url = a.optString(i);
|
||||||
|
strings.add(url);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void storeAccessToken(Context ctx, String hostPackage, String accessToken, ArrayList<String> scopes)
|
||||||
|
{
|
||||||
|
SharedPreferences prefs = getPrefsForHost(ctx, hostPackage);
|
||||||
|
|
||||||
|
Editor edit = prefs.edit();
|
||||||
|
edit.putString(PREF_KEY_TOKEN, accessToken);
|
||||||
|
String scopesString = stringArrayToString(scopes);
|
||||||
|
edit.putString(PREF_KEY_SCOPE, scopesString);
|
||||||
|
edit.commit();
|
||||||
|
Log.d(_tag, "stored access token " + accessToken.substring(0, 4)+"... for "+scopes.size()+" scopes ("+scopesString+").");
|
||||||
|
|
||||||
|
SharedPreferences hostPrefs = ctx.getSharedPreferences("KP2A.PluginAccess.hosts", Context.MODE_PRIVATE);
|
||||||
|
if (!hostPrefs.contains(hostPackage))
|
||||||
|
{
|
||||||
|
hostPrefs.edit().putString(hostPackage, "").commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void preparePopup(Object popupMenu)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Field[] fields = popupMenu.getClass().getDeclaredFields();
|
||||||
|
for (Field field : fields) {
|
||||||
|
if ("mPopup".equals(field.getName())) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
Object menuPopupHelper = field.get(popupMenu);
|
||||||
|
Class<?> classPopupHelper = Class.forName(menuPopupHelper
|
||||||
|
.getClass().getName());
|
||||||
|
Method setForceIcons = classPopupHelper.getMethod(
|
||||||
|
"setForceShowIcon", boolean.class);
|
||||||
|
setForceIcons.invoke(menuPopupHelper, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SharedPreferences getPrefsForHost(Context ctx,
|
||||||
|
String hostPackage) {
|
||||||
|
SharedPreferences prefs = ctx.getSharedPreferences("KP2A.PluginAccess."+hostPackage, Context.MODE_PRIVATE);
|
||||||
|
return prefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String tryGetAccessToken(Context ctx, String hostPackage, ArrayList<String> scopes) {
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(hostPackage))
|
||||||
|
{
|
||||||
|
Log.d(_tag, "hostPackage is empty!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Log.d(_tag, "trying to find prefs for "+hostPackage);
|
||||||
|
SharedPreferences prefs = getPrefsForHost(ctx, hostPackage);
|
||||||
|
String scopesString = prefs.getString(PREF_KEY_SCOPE, "");
|
||||||
|
Log.d(_tag, "available scopes: "+ scopesString);
|
||||||
|
ArrayList<String> 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.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSubset(ArrayList<String> requiredScopes,
|
||||||
|
ArrayList<String> availableScopes) {
|
||||||
|
for (String r: requiredScopes){
|
||||||
|
if (availableScopes.indexOf(r)<0)
|
||||||
|
{
|
||||||
|
Log.d(_tag, "Scope "+r+" not available. "+availableScopes.size());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeAccessToken(Context ctx, String hostPackage,
|
||||||
|
String accessToken) {
|
||||||
|
SharedPreferences prefs = getPrefsForHost(ctx, hostPackage);
|
||||||
|
|
||||||
|
Log.d(_tag, "removing AccessToken.");
|
||||||
|
if (prefs.getString(PREF_KEY_TOKEN, "").equals(accessToken))
|
||||||
|
{
|
||||||
|
Editor edit = prefs.edit();
|
||||||
|
edit.clear();
|
||||||
|
edit.commit();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedPreferences hostPrefs = ctx.getSharedPreferences("KP2A.PluginAccess.hosts", Context.MODE_PRIVATE);
|
||||||
|
if (hostPrefs.contains(hostPackage))
|
||||||
|
{
|
||||||
|
hostPrefs.edit().remove(hostPackage).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<String> getAllHostPackages(Context ctx)
|
||||||
|
{
|
||||||
|
SharedPreferences prefs = ctx.getSharedPreferences("KP2A.PluginAccess.hosts", Context.MODE_PRIVATE);
|
||||||
|
Set<String> result = new HashSet<String>();
|
||||||
|
for (String host: prefs.getAll().keySet())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PackageInfo info = ctx.getPackageManager().getPackageInfo(host, PackageManager.GET_META_DATA);
|
||||||
|
//if we get here, the package is still there
|
||||||
|
result.add(host);
|
||||||
|
}
|
||||||
|
catch (PackageManager.NameNotFoundException e)
|
||||||
|
{
|
||||||
|
//host gone. ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a valid access token or throws PluginAccessException
|
||||||
|
*/
|
||||||
|
public static String getAccessToken(Context context, String hostPackage,
|
||||||
|
ArrayList<String> scopes) throws PluginAccessException {
|
||||||
|
String accessToken = tryGetAccessToken(context, hostPackage, scopes);
|
||||||
|
if (accessToken == null)
|
||||||
|
throw new PluginAccessException(hostPackage, scopes);
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package keepass2android.pluginsdk;
|
||||||
|
|
||||||
|
public class KeepassDefs {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default identifier string for the title field. Should not contain
|
||||||
|
/// spaces, tabs or other whitespace.
|
||||||
|
/// </summary>
|
||||||
|
public static String TitleField = "Title";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default identifier string for the user name field. Should not contain
|
||||||
|
/// spaces, tabs or other whitespace.
|
||||||
|
/// </summary>
|
||||||
|
public static String UserNameField = "UserName";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default identifier string for the password field. Should not contain
|
||||||
|
/// spaces, tabs or other whitespace.
|
||||||
|
/// </summary>
|
||||||
|
public static String PasswordField = "Password";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default identifier string for the URL field. Should not contain
|
||||||
|
/// spaces, tabs or other whitespace.
|
||||||
|
/// </summary>
|
||||||
|
public static String UrlField = "URL";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default identifier string for the notes field. Should not contain
|
||||||
|
/// spaces, tabs or other whitespace.
|
||||||
|
/// </summary>
|
||||||
|
public static String NotesField = "Notes";
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean IsStandardField(String strFieldName)
|
||||||
|
{
|
||||||
|
if(strFieldName == null)
|
||||||
|
return false;
|
||||||
|
if(strFieldName.equals(TitleField)) return true;
|
||||||
|
if(strFieldName.equals(UserNameField)) return true;
|
||||||
|
if(strFieldName.equals(PasswordField)) return true;
|
||||||
|
if(strFieldName.equals(UrlField)) return true;
|
||||||
|
if(strFieldName.equals(NotesField)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package keepass2android.pluginsdk;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
public class 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
|
||||||
|
*/
|
||||||
|
public static Intent getAddEntryIntent(HashMap<String, String> fields, ArrayList<String> protectedFields)
|
||||||
|
{
|
||||||
|
return getAddEntryIntent(new JSONObject(fields).toString(), protectedFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Intent getAddEntryIntent(String outputData, ArrayList<String> protectedFields)
|
||||||
|
{
|
||||||
|
Intent startKp2aIntent = new Intent(Strings.ACTION_START_WITH_TASK);
|
||||||
|
startKp2aIntent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
startKp2aIntent.putExtra("KP2A_APPTASK", "CreateEntryThenCloseTask");
|
||||||
|
startKp2aIntent.putExtra("ShowUserNotifications", "false"); //KP2A expects a StringExtra
|
||||||
|
startKp2aIntent.putExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA, outputData);
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public static Intent getOpenEntryIntent(String searchText, boolean showUserNotifications, boolean closeAfterOpen)
|
||||||
|
{
|
||||||
|
Intent startKp2aIntent = new Intent(Strings.ACTION_START_WITH_TASK);
|
||||||
|
startKp2aIntent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
startKp2aIntent.putExtra("KP2A_APPTASK", "SearchUrlTask");
|
||||||
|
startKp2aIntent.putExtra("ShowUserNotifications", String.valueOf(showUserNotifications));
|
||||||
|
startKp2aIntent.putExtra("CloseAfterCreate", String.valueOf(closeAfterOpen));
|
||||||
|
startKp2aIntent.putExtra("UrlToSearch", searchText);
|
||||||
|
return startKp2aIntent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public static Intent getQueryEntryIntent(String searchText)
|
||||||
|
{
|
||||||
|
Intent i = new Intent(Strings.ACTION_QUERY_CREDENTIALS);
|
||||||
|
if (!TextUtils.isEmpty(searchText))
|
||||||
|
i.putExtra(Strings.EXTRA_QUERY_STRING, searchText);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public static Intent getQueryEntryIntentForOwnPackage()
|
||||||
|
{
|
||||||
|
return new 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
|
||||||
|
*/
|
||||||
|
public static HashMap<String, String> getEntryFieldsFromIntent(Intent intent)
|
||||||
|
{
|
||||||
|
HashMap<String, String> res = new HashMap<String, String>();
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(intent.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA));
|
||||||
|
for(Iterator<String> iter = json.keys();iter.hasNext();) {
|
||||||
|
String key = iter.next();
|
||||||
|
String value = json.get(key).toString();
|
||||||
|
res.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package keepass2android.pluginsdk;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import android.R.anim;
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class PluginAccessBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
private static final String _tag = "Kp2aPluginSDK";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context ctx, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
android.util.Log.d(_tag, "received broadcast with action="+action);
|
||||||
|
if (action == null)
|
||||||
|
return;
|
||||||
|
if (action.equals(Strings.ACTION_TRIGGER_REQUEST_ACCESS))
|
||||||
|
{
|
||||||
|
requestAccess(ctx, intent);
|
||||||
|
} else if (action.equals(Strings.ACTION_RECEIVE_ACCESS))
|
||||||
|
{
|
||||||
|
receiveAccess(ctx, intent);
|
||||||
|
} else if (action.equals(Strings.ACTION_REVOKE_ACCESS))
|
||||||
|
{
|
||||||
|
revokeAccess(ctx, intent);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//TODO handle unexpected action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void revokeAccess(Context ctx, Intent intent) {
|
||||||
|
String senderPackage = intent.getStringExtra(Strings.EXTRA_SENDER);
|
||||||
|
String accessToken = intent.getStringExtra(Strings.EXTRA_ACCESS_TOKEN);
|
||||||
|
//this intent must send the invalid(ated) token to prevent malicious apps
|
||||||
|
//from revoking access of all plugins.
|
||||||
|
AccessManager.removeAccessToken(ctx, senderPackage, accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void receiveAccess(Context ctx, Intent intent) {
|
||||||
|
String senderPackage = intent.getStringExtra(Strings.EXTRA_SENDER);
|
||||||
|
String accessToken = intent.getStringExtra(Strings.EXTRA_ACCESS_TOKEN);
|
||||||
|
AccessManager.storeAccessToken(ctx, senderPackage, accessToken, getScopes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestAccess(Context ctx, Intent intent) {
|
||||||
|
String senderPackage = intent.getStringExtra(Strings.EXTRA_SENDER);
|
||||||
|
String requestToken = intent.getStringExtra(Strings.EXTRA_REQUEST_TOKEN);
|
||||||
|
Intent rpi = new Intent(Strings.ACTION_REQUEST_ACCESS);
|
||||||
|
rpi.setPackage(senderPackage);
|
||||||
|
rpi.putExtra(Strings.EXTRA_SENDER, ctx.getPackageName());
|
||||||
|
rpi.putExtra(Strings.EXTRA_REQUEST_TOKEN, requestToken);
|
||||||
|
|
||||||
|
String token = AccessManager.tryGetAccessToken(ctx, senderPackage, getScopes());
|
||||||
|
if (token != null)
|
||||||
|
{
|
||||||
|
rpi.putExtra(Strings.EXTRA_ACCESS_TOKEN, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
rpi.putStringArrayListExtra(Strings.EXTRA_SCOPES, getScopes());
|
||||||
|
Log.d(_tag, "requesting access for "+getScopes().size()+" tokens.");
|
||||||
|
ctx.sendBroadcast(rpi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the list of required scopes for this plugin.
|
||||||
|
*/
|
||||||
|
abstract public ArrayList<String> getScopes();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package keepass2android.pluginsdk;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class PluginAccessException extends Exception {
|
||||||
|
|
||||||
|
public PluginAccessException(String what)
|
||||||
|
{
|
||||||
|
super(what);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginAccessException(String hostPackage, ArrayList<String> scopes) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,303 @@
|
|||||||
|
package keepass2android.pluginsdk;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public abstract class PluginActionBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
protected abstract class PluginActionBase
|
||||||
|
{
|
||||||
|
protected Context _context;
|
||||||
|
protected Intent _intent;
|
||||||
|
|
||||||
|
|
||||||
|
public PluginActionBase(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_intent = intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostPackage() {
|
||||||
|
return _intent.getStringExtra(Strings.EXTRA_SENDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Context getContext()
|
||||||
|
{
|
||||||
|
return _context;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract class PluginEntryActionBase extends PluginActionBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public PluginEntryActionBase(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
super(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HashMap<String, String> getEntryFieldsFromIntent()
|
||||||
|
{
|
||||||
|
HashMap<String, String> res = new HashMap<String, String>();
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(_intent.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA));
|
||||||
|
for(Iterator<String> iter = json.keys();iter.hasNext();) {
|
||||||
|
String key = iter.next();
|
||||||
|
String value = json.get(key).toString();
|
||||||
|
Log.d("KP2APluginSDK", "received " + key+"/"+value);
|
||||||
|
res.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String[] getProtectedFieldsListFromIntent()
|
||||||
|
{
|
||||||
|
return _intent.getStringArrayExtra(Strings.EXTRA_PROTECTED_FIELDS_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getEntryId()
|
||||||
|
{
|
||||||
|
return _intent.getStringExtra(Strings.EXTRA_ENTRY_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setEntryField(String fieldId, String fieldValue, boolean isProtected) throws PluginAccessException
|
||||||
|
{
|
||||||
|
Intent i = new Intent(Strings.ACTION_SET_ENTRY_FIELD);
|
||||||
|
ArrayList<String> scope = new ArrayList<String>();
|
||||||
|
scope.add(Strings.SCOPE_CURRENT_ENTRY);
|
||||||
|
i.putExtra(Strings.EXTRA_ACCESS_TOKEN, AccessManager.getAccessToken(_context, getHostPackage(), scope));
|
||||||
|
i.setPackage(getHostPackage());
|
||||||
|
i.putExtra(Strings.EXTRA_SENDER, _context.getPackageName());
|
||||||
|
i.putExtra(Strings.EXTRA_FIELD_VALUE, fieldValue);
|
||||||
|
i.putExtra(Strings.EXTRA_ENTRY_ID, getEntryId());
|
||||||
|
i.putExtra(Strings.EXTRA_FIELD_ID, fieldId);
|
||||||
|
i.putExtra(Strings.EXTRA_FIELD_PROTECTED, isProtected);
|
||||||
|
|
||||||
|
_context.sendBroadcast(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ActionSelectedAction extends PluginEntryActionBase
|
||||||
|
{
|
||||||
|
public ActionSelectedAction(Context ctx, Intent intent) {
|
||||||
|
super(ctx, intent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the Bundle associated with the action. This bundle can be set in OpenEntry.add(Entry)FieldAction
|
||||||
|
*/
|
||||||
|
public Bundle getActionData()
|
||||||
|
{
|
||||||
|
return _intent.getBundleExtra(Strings.EXTRA_ACTION_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the field id which was selected. null if an entry action (in the options menu) was selected.
|
||||||
|
*/
|
||||||
|
public String getFieldId()
|
||||||
|
{
|
||||||
|
return _intent.getStringExtra(Strings.EXTRA_FIELD_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true if an entry action, i.e. an option from the options menu, was selected. False if an option
|
||||||
|
* in a popup menu for a certain field was selected.
|
||||||
|
*/
|
||||||
|
public boolean isEntryAction()
|
||||||
|
{
|
||||||
|
return getFieldId() == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return a hashmap containing the entry fields in key/value form
|
||||||
|
*/
|
||||||
|
public HashMap<String, String> getEntryFields()
|
||||||
|
{
|
||||||
|
return getEntryFieldsFromIntent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return an array with the keys of all protected fields in the entry
|
||||||
|
*/
|
||||||
|
public String[] getProtectedFieldsList()
|
||||||
|
{
|
||||||
|
return getProtectedFieldsListFromIntent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class CloseEntryViewAction extends PluginEntryActionBase
|
||||||
|
{
|
||||||
|
public CloseEntryViewAction(Context context, Intent intent) {
|
||||||
|
super(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEntryId()
|
||||||
|
{
|
||||||
|
return _intent.getStringExtra(Strings.EXTRA_ENTRY_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class OpenEntryAction extends PluginEntryActionBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public OpenEntryAction(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
super(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public HashMap<String, String> getEntryFields()
|
||||||
|
{
|
||||||
|
return getEntryFieldsFromIntent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return an array with the keys of all protected fields in the entry
|
||||||
|
*/
|
||||||
|
public String[] getProtectedFieldsList()
|
||||||
|
{
|
||||||
|
return getProtectedFieldsListFromIntent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEntryAction(String actionDisplayText, int actionIconResourceId, Bundle actionData) throws PluginAccessException
|
||||||
|
{
|
||||||
|
addEntryFieldAction(null, null, actionDisplayText, actionIconResourceId, actionData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEntryFieldAction(String actionId, String fieldId, String actionDisplayText, int actionIconResourceId, Bundle actionData) throws PluginAccessException
|
||||||
|
{
|
||||||
|
Intent i = new Intent(Strings.ACTION_ADD_ENTRY_ACTION);
|
||||||
|
ArrayList<String> scope = new ArrayList<String>();
|
||||||
|
scope.add(Strings.SCOPE_CURRENT_ENTRY);
|
||||||
|
i.putExtra(Strings.EXTRA_ACCESS_TOKEN, AccessManager.getAccessToken(_context, getHostPackage(), scope));
|
||||||
|
i.setPackage(getHostPackage());
|
||||||
|
i.putExtra(Strings.EXTRA_SENDER, _context.getPackageName());
|
||||||
|
i.putExtra(Strings.EXTRA_ACTION_DATA, actionData);
|
||||||
|
i.putExtra(Strings.EXTRA_ACTION_DISPLAY_TEXT, actionDisplayText);
|
||||||
|
i.putExtra(Strings.EXTRA_ACTION_ICON_RES_ID, actionIconResourceId);
|
||||||
|
i.putExtra(Strings.EXTRA_ENTRY_ID, getEntryId());
|
||||||
|
i.putExtra(Strings.EXTRA_FIELD_ID, fieldId);
|
||||||
|
i.putExtra(Strings.EXTRA_ACTION_ID, actionId);
|
||||||
|
|
||||||
|
_context.sendBroadcast(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class DatabaseAction extends PluginActionBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public DatabaseAction(Context context, Intent intent) {
|
||||||
|
super(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileDisplayName()
|
||||||
|
{
|
||||||
|
return _intent.getStringExtra(Strings.EXTRA_DATABASE_FILE_DISPLAYNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilePath()
|
||||||
|
{
|
||||||
|
return _intent.getStringExtra(Strings.EXTRA_DATABASE_FILEPATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAction()
|
||||||
|
{
|
||||||
|
return _intent.getAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//EntryOutputModified is very similar to OpenEntry because it receives the same
|
||||||
|
//data (+ the field id which was modified)
|
||||||
|
protected class EntryOutputModifiedAction extends OpenEntryAction
|
||||||
|
{
|
||||||
|
|
||||||
|
public EntryOutputModifiedAction(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
super(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModifiedFieldId()
|
||||||
|
{
|
||||||
|
return _intent.getStringExtra(Strings.EXTRA_FIELD_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context ctx, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
android.util.Log.d("KP2A.pluginsdk", "received broadcast in PluginActionBroadcastReceiver with action="+action);
|
||||||
|
if (action == null)
|
||||||
|
return;
|
||||||
|
if (action.equals(Strings.ACTION_OPEN_ENTRY))
|
||||||
|
{
|
||||||
|
openEntry(new OpenEntryAction(ctx, intent));
|
||||||
|
}
|
||||||
|
else if (action.equals(Strings.ACTION_CLOSE_ENTRY_VIEW))
|
||||||
|
{
|
||||||
|
closeEntryView(new CloseEntryViewAction(ctx, intent));
|
||||||
|
}
|
||||||
|
else if (action.equals(Strings.ACTION_ENTRY_ACTION_SELECTED))
|
||||||
|
{
|
||||||
|
actionSelected(new ActionSelectedAction(ctx, intent));
|
||||||
|
}
|
||||||
|
else if (action.equals(Strings.ACTION_ENTRY_OUTPUT_MODIFIED))
|
||||||
|
{
|
||||||
|
entryOutputModified(new EntryOutputModifiedAction(ctx, intent));
|
||||||
|
}
|
||||||
|
else if (action.equals(Strings.ACTION_LOCK_DATABASE)
|
||||||
|
|| action.equals(Strings.ACTION_UNLOCK_DATABASE)
|
||||||
|
|| action.equals(Strings.ACTION_OPEN_DATABASE)
|
||||||
|
|| action.equals(Strings.ACTION_CLOSE_DATABASE))
|
||||||
|
{
|
||||||
|
dbAction(new DatabaseAction(ctx, intent));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//TODO handle unexpected action
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void closeEntryView(CloseEntryViewAction closeEntryView) {}
|
||||||
|
|
||||||
|
protected void actionSelected(ActionSelectedAction actionSelected) {}
|
||||||
|
|
||||||
|
protected void openEntry(OpenEntryAction oe) {}
|
||||||
|
|
||||||
|
protected void entryOutputModified(EntryOutputModifiedAction eom) {}
|
||||||
|
|
||||||
|
protected void dbAction(DatabaseAction db) {}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
package keepass2android.pluginsdk;
|
||||||
|
|
||||||
|
public class Strings {
|
||||||
|
/**
|
||||||
|
* Plugin is notified about actions like open/close/update a database.
|
||||||
|
*/
|
||||||
|
public static final String SCOPE_DATABASE_ACTIONS = "keepass2android.SCOPE_DATABASE_ACTIONS";
|
||||||
|
/**
|
||||||
|
* Plugin is notified when an entry is opened.
|
||||||
|
*/
|
||||||
|
public static final String SCOPE_CURRENT_ENTRY = "keepass2android.SCOPE_CURRENT_ENTRY";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin may query credentials for its own package
|
||||||
|
*/
|
||||||
|
public static final String SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE = "keepass2android.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin may query credentials for a deliberate package
|
||||||
|
*/
|
||||||
|
public static final String SCOPE_QUERY_CREDENTIALS = "keepass2android.SCOPE_QUERY_CREDENTIALS";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra key to transfer a (json serialized) list of scopes
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_SCOPES = "keepass2android.EXTRA_SCOPES";
|
||||||
|
|
||||||
|
|
||||||
|
public static final String EXTRA_PLUGIN_PACKAGE = "keepass2android.EXTRA_PLUGIN_PACKAGE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra key for sending the package name of the sender of a broadcast.
|
||||||
|
* Should be set in every broadcast.
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_SENDER = "keepass2android.EXTRA_SENDER";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra key for sending a request token. The request token is passed from
|
||||||
|
* KP2A to the plugin. It's used in the authorization process.
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_REQUEST_TOKEN = "keepass2android.EXTRA_REQUEST_TOKEN";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action to start KP2A with an AppTask
|
||||||
|
*/
|
||||||
|
public static final String ACTION_START_WITH_TASK = "keepass2android.ACTION_START_WITH_TASK";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action sent from KP2A to the plugin to indicate that the plugin should request
|
||||||
|
* access (sending it's scopes)
|
||||||
|
*/
|
||||||
|
public static final String ACTION_TRIGGER_REQUEST_ACCESS = "keepass2android.ACTION_TRIGGER_REQUEST_ACCESS";
|
||||||
|
/**
|
||||||
|
* Action sent from the plugin to KP2A including the scopes.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_REQUEST_ACCESS = "keepass2android.ACTION_REQUEST_ACCESS";
|
||||||
|
/**
|
||||||
|
* Action sent from the KP2A to the plugin when the user grants access.
|
||||||
|
* Will contain an access token.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_RECEIVE_ACCESS = "keepass2android.ACTION_RECEIVE_ACCESS";
|
||||||
|
/**
|
||||||
|
* Action sent from KP2A to the plugin to indicate that access is not or no longer valid.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_REVOKE_ACCESS = "keepass2android.ACTION_REVOKE_ACCESS";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action for startActivity(). Opens an activity in the Plugin Host to edit the plugin settings (i.e. enable it)
|
||||||
|
*/
|
||||||
|
public static final String ACTION_EDIT_PLUGIN_SETTINGS = "keepass2android.ACTION_EDIT_PLUGIN_SETTINGS";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action sent from KP2A to the plugin to indicate that an entry was opened.
|
||||||
|
* The Intent contains the full entry data.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_OPEN_ENTRY= "keepass2android.ACTION_OPEN_ENTRY";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action sent from KP2A to the plugin to indicate that an entry output field was modified/added.
|
||||||
|
* The Intent contains the full new entry data.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_ENTRY_OUTPUT_MODIFIED= "keepass2android.ACTION_ENTRY_OUTPUT_MODIFIED";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action sent from KP2A to the plugin to indicate that an entry activity was closed.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_CLOSE_ENTRY_VIEW= "keepass2android.ACTION_CLOSE_ENTRY_VIEW";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra key for a string containing the GUID of the entry.
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_ENTRY_ID= "keepass2android.EXTRA_ENTRY_DATA";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Json serialized data of the PwEntry (C# class) representing the opened entry.
|
||||||
|
* currently not implemented.
|
||||||
|
*/
|
||||||
|
//public static final String EXTRA_ENTRY_DATA = "keepass2android.EXTRA_ENTRY_DATA";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Json serialized list of fields, transformed using the database context (i.e. placeholders are replaced already)
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_ENTRY_OUTPUT_DATA = "keepass2android.EXTRA_ENTRY_OUTPUT_DATA";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Json serialized lisf of field keys, specifying which field of the EXTRA_ENTRY_OUTPUT_DATA is protected.
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_PROTECTED_FIELDS_LIST = "keepass2android.EXTRA_PROTECTED_FIELDS_LIST";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra key for passing the access token (both ways)
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_ACCESS_TOKEN = "keepass2android.EXTRA_ACCESS_TOKEN";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action for an intent from the plugin to KP2A to add menu options regarding the currently open entry.
|
||||||
|
* Requires SCOPE_CURRENT_ENTRY.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_ADD_ENTRY_ACTION = "keepass2android.ACTION_ADD_ENTRY_ACTION";
|
||||||
|
|
||||||
|
public static final String EXTRA_ACTION_DISPLAY_TEXT = "keepass2android.EXTRA_ACTION_DISPLAY_TEXT";
|
||||||
|
public static final String EXTRA_ACTION_ICON_RES_ID = "keepass2android.EXTRA_ACTION_ICON_RES_ID";
|
||||||
|
|
||||||
|
public static final String EXTRA_FIELD_ID = "keepass2android.EXTRA_FIELD_ID";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to pass an id for the action. Each actionId may occur only once per field, otherwise the previous
|
||||||
|
* action with same id is replaced by the new action.
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_ACTION_ID = "keepass2android.EXTRA_ACTION_ID";
|
||||||
|
|
||||||
|
/** Extra for ACTION_ADD_ENTRY_ACTION and ACTION_ENTRY_ACTION_SELECTED to pass data specifying the action parameters.*/
|
||||||
|
public static final String EXTRA_ACTION_DATA = "keepass2android.EXTRA_ACTION_DATA";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action for an intent from KP2A to the plugin when an action added with ACTION_ADD_ENTRY_ACTION was selected by the user.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final String ACTION_ENTRY_ACTION_SELECTED = "keepass2android.ACTION_ENTRY_ACTION_SELECTED";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra key for the string which is used to query the credentials. This should be either a URL for
|
||||||
|
* a web login (google.com or a full URI) or something in the form "androidapp://com.my.package"
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_QUERY_STRING = "keepass2android.EXTRA_QUERY_STRING";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action when plugin wants to query credentials for its own package
|
||||||
|
*/
|
||||||
|
public static final String 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
|
||||||
|
*/
|
||||||
|
public static final String 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.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_SET_ENTRY_FIELD = "keepass2android.ACTION_SET_ENTRY_FIELD";
|
||||||
|
|
||||||
|
/** Actions for an intent from KP2A to the plugin to inform that a database was opened, closed, quicklocked or quickunlocked.*/
|
||||||
|
public static final String ACTION_OPEN_DATABASE = "keepass2android.ACTION_OPEN_DATABASE";
|
||||||
|
public static final String ACTION_CLOSE_DATABASE = "keepass2android.ACTION_CLOSE_DATABASE";
|
||||||
|
public static final String ACTION_LOCK_DATABASE = "keepass2android.ACTION_LOCK_DATABASE";
|
||||||
|
public static final String ACTION_UNLOCK_DATABASE = "keepass2android.ACTION_UNLOCK_DATABASE";
|
||||||
|
|
||||||
|
/** Extra for ACTION_OPEN_DATABASE and ACTION_CLOSE_DATABASE containing a filepath which is used
|
||||||
|
* by KP2A internally to identify the file. Use only where necessary, might contain credentials
|
||||||
|
* for accessing the file (on remote storage).*/
|
||||||
|
public static final String EXTRA_DATABASE_FILEPATH = "keepass2android.EXTRA_DATABASE_FILEPATH";
|
||||||
|
/** Extra for ACTION_OPEN_DATABASE and ACTION_CLOSE_DATABASE containing a filepath which can be
|
||||||
|
* displayed to the user.*/
|
||||||
|
public static final String EXTRA_DATABASE_FILE_DISPLAYNAME = "keepass2android.EXTRA_DATABASE_FILE_DISPLAYNAME";
|
||||||
|
|
||||||
|
|
||||||
|
public static final String EXTRA_FIELD_VALUE = "keepass2android.EXTRA_FIELD_VALUE";
|
||||||
|
public static final String EXTRA_FIELD_PROTECTED = "keepass2android.EXTRA_FIELD_PROTECTED";
|
||||||
|
|
||||||
|
public static final String PREFIX_STRING = "STRING_";
|
||||||
|
public static final String PREFIX_BINARY = "BINARY_";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user