aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'OpenPGP-Keychain/src/main')
-rw-r--r--OpenPGP-Keychain/src/main/AndroidManifest.xml8
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java4
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java39
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java45
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java132
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java88
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/AccountSettings.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettings.java)31
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/AppSettings.java54
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java)54
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java)74
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/WrongPackageSignatureException.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java)2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java)106
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountsListFragment.java176
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java)35
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsFragment.java119
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java)4
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java)85
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java)87
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java75
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/api_account_create_activity.xml21
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/api_account_settings_fragment.xml115
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/api_app_register_activity.xml2
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/api_app_settings_activity.xml16
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/api_app_settings_fragment.xml44
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/api_apps_list_content.xml2
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/key_list_fragment.xml5
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-de/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-de/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-el/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-el/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-es-rCO/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-es-rCO/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-es/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-es/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-fa-rIR/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-fr/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-fr/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-it-rIT/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-it-rIT/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-ja/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-ja/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-pl/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-pl/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-ru/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-ru/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-tr/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-tr/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-uk/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-uk/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/raw-zh/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw/help_about.html6
-rw-r--r--OpenPGP-Keychain/src/main/res/raw/help_start.html2
-rw-r--r--OpenPGP-Keychain/src/main/res/values/strings.xml4
63 files changed, 1197 insertions, 378 deletions
diff --git a/OpenPGP-Keychain/src/main/AndroidManifest.xml b/OpenPGP-Keychain/src/main/AndroidManifest.xml
index b1fbcf555..3ab39280e 100644
--- a/OpenPGP-Keychain/src/main/AndroidManifest.xml
+++ b/OpenPGP-Keychain/src/main/AndroidManifest.xml
@@ -384,24 +384,24 @@
<!-- Internal classes of the remote APIs (not exported) -->
<activity
- android:name="org.sufficientlysecure.keychain.service.remote.RemoteServiceActivity"
+ android:name="org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity"
android:exported="false"
android:label="@string/app_name" />
<!--android:launchMode="singleTop"-->
<!--android:process=":remote_api"-->
<activity
- android:name="org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity"
+ android:name=".remote.ui.AppsListActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:exported="false"
android:label="@string/title_api_registered_apps" />
<activity
- android:name="org.sufficientlysecure.keychain.service.remote.AppSettingsActivity"
+ android:name="org.sufficientlysecure.keychain.remote.ui.AppSettingsActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:exported="false" />
<!-- OpenPGP Remote API -->
<service
- android:name="org.sufficientlysecure.keychain.service.remote.OpenPgpService"
+ android:name="org.sufficientlysecure.keychain.remote.OpenPgpService"
android:enabled="true"
android:exported="true"
android:process=":remote_api">
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
index ff4abe56a..f9a7962ec 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
@@ -19,7 +19,7 @@ package org.sufficientlysecure.keychain;
import android.os.Environment;
import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity;
+import org.sufficientlysecure.keychain.remote.ui.AppsListActivity;
import org.sufficientlysecure.keychain.ui.DecryptActivity;
import org.sufficientlysecure.keychain.ui.EncryptActivity;
import org.sufficientlysecure.keychain.ui.ImportKeysActivity;
@@ -73,7 +73,7 @@ public final class Constants {
public static final Class ENCRYPT = EncryptActivity.class;
public static final Class DECRYPT = DecryptActivity.class;
public static final Class IMPORT_KEYS = ImportKeysActivity.class;
- public static final Class REGISTERED_APPS_LIST = RegisteredAppsListActivity.class;
+ public static final Class REGISTERED_APPS_LIST = AppsListActivity.class;
public static final Class[] ARRAY = new Class[]{KEY_LIST, ENCRYPT, DECRYPT,
IMPORT_KEYS, REGISTERED_APPS_LIST};
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
index 5f2354c24..6e4899fc2 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.provider;
import android.net.Uri;
import android.provider.BaseColumns;
+
import org.sufficientlysecure.keychain.Constants;
public class KeychainContract {
@@ -56,10 +57,15 @@ public class KeychainContract {
interface ApiAppsColumns {
String PACKAGE_NAME = "package_name";
String PACKAGE_SIGNATURE = "package_signature";
+ }
+
+ interface ApiAppsAccountsColumns {
+ String ACCOUNT_NAME = "account_name";
String KEY_ID = "key_id"; // not a database id
String ENCRYPTION_ALGORITHM = "encryption_algorithm";
String HASH_ALORITHM = "hash_algorithm";
String COMPRESSION = "compression";
+ String PACKAGE_NAME_FK = "package_name"; // foreign key to api_apps.package_name
}
public static final class KeyTypes {
@@ -87,7 +93,7 @@ public class KeychainContract {
public static final String PATH_KEYS = "keys";
public static final String BASE_API_APPS = "api_apps";
- public static final String PATH_BY_PACKAGE_NAME = "package_name";
+ public static final String PATH_ACCOUNTS = "accounts";
public static class KeyRings implements KeyRingsColumns, BaseColumns {
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
@@ -154,6 +160,7 @@ public class KeychainContract {
}
public static Uri buildSecretKeyRingsByEmailsUri(String emails) {
+ // TODO: encoded?
return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(PATH_BY_EMAILS)
.appendPath(emails).build();
}
@@ -262,16 +269,36 @@ public class KeychainContract {
/**
* Use if a single item is returned
*/
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_apps";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_app";
- public static Uri buildIdUri(String rowId) {
- return CONTENT_URI.buildUpon().appendPath(rowId).build();
+ public static Uri buildByPackageNameUri(String packageName) {
+ return CONTENT_URI.buildUpon().appendEncodedPath(packageName).build();
}
+ }
- public static Uri buildByPackageNameUri(String packageName) {
- return CONTENT_URI.buildUpon().appendPath(PATH_BY_PACKAGE_NAME).appendPath(packageName)
+ public static class ApiAccounts implements ApiAppsAccountsColumns, BaseColumns {
+ public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
+ .appendPath(BASE_API_APPS).build();
+
+ /**
+ * Use if multiple items get returned
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api_app.accounts";
+
+ /**
+ * Use if a single item is returned
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_app.account";
+
+ public static Uri buildBaseUri(String packageName) {
+ return CONTENT_URI.buildUpon().appendEncodedPath(packageName).appendPath(PATH_ACCOUNTS)
.build();
}
+
+ public static Uri buildByPackageAndAccountUri(String packageName, String accountName) {
+ return CONTENT_URI.buildUpon().appendEncodedPath(packageName).appendPath(PATH_ACCOUNTS)
+ .appendEncodedPath(accountName).build();
+ }
}
public static class DataStream {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 031a7d5ae..4abcec435 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -21,8 +21,10 @@ import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
+
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
+import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;
@@ -30,13 +32,14 @@ import org.sufficientlysecure.keychain.util.Log;
public class KeychainDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "apg.db";
- private static final int DATABASE_VERSION = 7;
+ private static final int DATABASE_VERSION = 8;
public interface Tables {
String KEY_RINGS = "key_rings";
String KEYS = "keys";
String USER_IDS = "user_ids";
String API_APPS = "api_apps";
+ String API_ACCOUNTS = "api_accounts";
}
private static final String CREATE_KEY_RINGS = "CREATE TABLE IF NOT EXISTS " + Tables.KEY_RINGS
@@ -61,26 +64,35 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ KeysColumns.KEY_DATA + " BLOB,"
+ KeysColumns.RANK + " INTEGER, "
+ KeysColumns.FINGERPRINT + " BLOB, "
- + KeysColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, FOREIGN KEY("
- + KeysColumns.KEY_RING_ROW_ID + ") REFERENCES " + Tables.KEY_RINGS + "("
- + BaseColumns._ID + ") ON DELETE CASCADE)";
+ + KeysColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, "
+ + "FOREIGN KEY(" + KeysColumns.KEY_RING_ROW_ID + ") REFERENCES "
+ + Tables.KEY_RINGS + "(" + BaseColumns._ID + ") ON DELETE CASCADE)";
private static final String CREATE_USER_IDS = "CREATE TABLE IF NOT EXISTS " + Tables.USER_IDS
+ " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ UserIdsColumns.USER_ID + " TEXT, "
+ UserIdsColumns.RANK + " INTEGER, "
- + UserIdsColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, FOREIGN KEY("
- + UserIdsColumns.KEY_RING_ROW_ID + ") REFERENCES " + Tables.KEY_RINGS + "("
- + BaseColumns._ID + ") ON DELETE CASCADE)";
+ + UserIdsColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, "
+ + "FOREIGN KEY(" + UserIdsColumns.KEY_RING_ROW_ID + ") REFERENCES "
+ + Tables.KEY_RINGS + "(" + BaseColumns._ID + ") ON DELETE CASCADE)";
private static final String CREATE_API_APPS = "CREATE TABLE IF NOT EXISTS " + Tables.API_APPS
+ " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
- + ApiAppsColumns.PACKAGE_NAME + " TEXT UNIQUE, "
- + ApiAppsColumns.PACKAGE_SIGNATURE + " BLOB, "
- + ApiAppsColumns.KEY_ID + " INT64, "
- + ApiAppsColumns.ENCRYPTION_ALGORITHM + " INTEGER, "
- + ApiAppsColumns.HASH_ALORITHM + " INTEGER, "
- + ApiAppsColumns.COMPRESSION + " INTEGER)";
+ + ApiAppsColumns.PACKAGE_NAME + " TEXT NOT NULL UNIQUE, "
+ + ApiAppsColumns.PACKAGE_SIGNATURE + " BLOB)";
+
+ private static final String CREATE_API_APPS_ACCOUNTS = "CREATE TABLE IF NOT EXISTS " + Tables.API_ACCOUNTS
+ + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ + ApiAppsAccountsColumns.ACCOUNT_NAME + " TEXT NOT NULL, "
+ + ApiAppsAccountsColumns.KEY_ID + " INT64, "
+ + ApiAppsAccountsColumns.ENCRYPTION_ALGORITHM + " INTEGER, "
+ + ApiAppsAccountsColumns.HASH_ALORITHM + " INTEGER, "
+ + ApiAppsAccountsColumns.COMPRESSION + " INTEGER, "
+ + ApiAppsAccountsColumns.PACKAGE_NAME_FK + " TEXT NOT NULL, "
+ + "UNIQUE(" + ApiAppsAccountsColumns.ACCOUNT_NAME + ", "
+ + ApiAppsAccountsColumns.PACKAGE_NAME_FK + "), "
+ + "FOREIGN KEY(" + ApiAppsAccountsColumns.PACKAGE_NAME_FK + ") REFERENCES "
+ + Tables.API_APPS + "(" + ApiAppsColumns.PACKAGE_NAME + ") ON DELETE CASCADE)";
KeychainDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -94,6 +106,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
db.execSQL(CREATE_KEYS);
db.execSQL(CREATE_USER_IDS);
db.execSQL(CREATE_API_APPS);
+ db.execSQL(CREATE_API_APPS_ACCOUNTS);
}
@Override
@@ -133,6 +146,12 @@ public class KeychainDatabase extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.FINGERPRINT
+ " BLOB;");
break;
+ case 7:
+ // new db layout for api apps
+ db.execSQL("DROP TABLE IF EXISTS " + Tables.API_APPS);
+ db.execSQL(CREATE_API_APPS);
+ db.execSQL(CREATE_API_APPS_ACCOUNTS);
+ break;
default:
break;
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
index 746449f7e..6469da978 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,8 +28,17 @@ import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;
+
import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.provider.KeychainContract.*;
+import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts;
+import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.util.Log;
@@ -71,8 +80,9 @@ public class KeychainProvider extends ContentProvider {
private static final int SECRET_KEY_RING_USER_ID_BY_ROW_ID = 222;
private static final int API_APPS = 301;
- private static final int API_APPS_BY_ROW_ID = 302;
private static final int API_APPS_BY_PACKAGE_NAME = 303;
+ private static final int API_ACCOUNTS = 304;
+ private static final int API_ACCOUNTS_BY_ACCOUNT_NAME = 306;
private static final int UNIFIED_KEY_RING = 401;
@@ -229,11 +239,22 @@ public class KeychainProvider extends ContentProvider {
/**
* API apps
+ *
+ * <pre>
+ * api_apps
+ * api_apps/_ (package name)
+ *
+ * api_apps/_/accounts
+ * api_apps/_/accounts/_ (account name)
+ * </pre>
*/
matcher.addURI(authority, KeychainContract.BASE_API_APPS, API_APPS);
- matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/#", API_APPS_BY_ROW_ID);
- matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/"
- + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_APPS_BY_PACKAGE_NAME);
+ matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*", API_APPS_BY_PACKAGE_NAME);
+
+ matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/"
+ + KeychainContract.PATH_ACCOUNTS, API_ACCOUNTS);
+ matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/"
+ + KeychainContract.PATH_ACCOUNTS + "/*", API_ACCOUNTS_BY_ACCOUNT_NAME);
/**
* data stream
@@ -302,10 +323,15 @@ public class KeychainProvider extends ContentProvider {
case API_APPS:
return ApiApps.CONTENT_TYPE;
- case API_APPS_BY_ROW_ID:
case API_APPS_BY_PACKAGE_NAME:
return ApiApps.CONTENT_ITEM_TYPE;
+ case API_ACCOUNTS:
+ return ApiAccounts.CONTENT_TYPE;
+
+ case API_ACCOUNTS_BY_ACCOUNT_NAME:
+ return ApiAccounts.CONTENT_ITEM_TYPE;
+
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
@@ -506,7 +532,6 @@ public class KeychainProvider extends ContentProvider {
}
break;
-
case PUBLIC_KEY_RING:
case SECRET_KEY_RING:
qb = buildKeyRingQuery(qb, match);
@@ -516,7 +541,6 @@ public class KeychainProvider extends ContentProvider {
}
break;
-
case PUBLIC_KEY_RING_BY_ROW_ID:
case SECRET_KEY_RING_BY_ROW_ID:
qb = buildKeyRingQuery(qb, match);
@@ -529,7 +553,6 @@ public class KeychainProvider extends ContentProvider {
}
break;
-
case PUBLIC_KEY_RING_BY_MASTER_KEY_ID:
case SECRET_KEY_RING_BY_MASTER_KEY_ID:
qb = buildKeyRingQuery(qb, match);
@@ -542,7 +565,6 @@ public class KeychainProvider extends ContentProvider {
}
break;
-
case SECRET_KEY_RING_BY_KEY_ID:
case PUBLIC_KEY_RING_BY_KEY_ID:
qb = buildKeyRingQueryWithSpecificKey(qb, match);
@@ -555,7 +577,6 @@ public class KeychainProvider extends ContentProvider {
}
break;
-
case SECRET_KEY_RING_BY_EMAILS:
case PUBLIC_KEY_RING_BY_EMAILS:
qb = buildKeyRingQuery(qb, match);
@@ -585,7 +606,6 @@ public class KeychainProvider extends ContentProvider {
}
break;
-
case SECRET_KEY_RING_BY_LIKE_EMAIL:
case PUBLIC_KEY_RING_BY_LIKE_EMAIL:
qb = buildKeyRingQuery(qb, match);
@@ -601,7 +621,6 @@ public class KeychainProvider extends ContentProvider {
+ "))");
break;
-
case PUBLIC_KEY_RING_KEY:
case SECRET_KEY_RING_KEY:
qb.setTables(Tables.KEYS);
@@ -614,7 +633,6 @@ public class KeychainProvider extends ContentProvider {
qb.setProjectionMap(getProjectionMapForKeys());
break;
-
case PUBLIC_KEY_RING_KEY_BY_ROW_ID:
case SECRET_KEY_RING_KEY_BY_ROW_ID:
qb.setTables(Tables.KEYS);
@@ -630,7 +648,6 @@ public class KeychainProvider extends ContentProvider {
qb.setProjectionMap(getProjectionMapForKeys());
break;
-
case PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID:
qb.setTables(Tables.USER_IDS + " INNER JOIN " + Tables.KEY_RINGS + " ON " + "("
+ Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "."
@@ -641,7 +658,6 @@ public class KeychainProvider extends ContentProvider {
qb.setProjectionMap(getProjectionMapForUserIds());
break;
-
case PUBLIC_KEY_RING_USER_ID:
case SECRET_KEY_RING_USER_ID:
qb.setTables(Tables.USER_IDS);
@@ -649,7 +665,6 @@ public class KeychainProvider extends ContentProvider {
qb.appendWhereEscapeString(uri.getPathSegments().get(2));
break;
-
case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID:
case SECRET_KEY_RING_USER_ID_BY_ROW_ID:
qb.setTables(Tables.USER_IDS);
@@ -660,25 +675,31 @@ public class KeychainProvider extends ContentProvider {
qb.appendWhereEscapeString(uri.getLastPathSegment());
break;
-
case API_APPS:
qb.setTables(Tables.API_APPS);
break;
- case API_APPS_BY_ROW_ID:
+ case API_APPS_BY_PACKAGE_NAME:
qb.setTables(Tables.API_APPS);
-
- qb.appendWhere(BaseColumns._ID + " = ");
+ qb.appendWhere(ApiApps.PACKAGE_NAME + " = ");
qb.appendWhereEscapeString(uri.getLastPathSegment());
break;
- case API_APPS_BY_PACKAGE_NAME:
- qb.setTables(Tables.API_APPS);
- qb.appendWhere(ApiApps.PACKAGE_NAME + " = ");
- qb.appendWhereEscapeString(uri.getPathSegments().get(2));
+ case API_ACCOUNTS:
+ qb.setTables(Tables.API_ACCOUNTS);
break;
+ case API_ACCOUNTS_BY_ACCOUNT_NAME:
+ qb.setTables(Tables.API_ACCOUNTS + " INNER JOIN " + Tables.API_APPS + " ON " + "("
+ + Tables.API_APPS + "." + ApiApps.PACKAGE_NAME + " = " + Tables.API_ACCOUNTS + "."
+ + ApiAccounts.PACKAGE_NAME_FK + " )");
+ qb.appendWhere(Tables.API_APPS + "." + ApiApps.PACKAGE_NAME + " = ");
+ qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+
+ qb.appendWhere(" AND " + Tables.API_ACCOUNTS + "." + ApiAccounts.ACCOUNT_NAME + " = ");
+ qb.appendWhereEscapeString(uri.getLastPathSegment());
+ break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
@@ -735,12 +756,14 @@ public class KeychainProvider extends ContentProvider {
values.put(Keys.TYPE, KeyTypes.PUBLIC);
rowId = db.insertOrThrow(Tables.KEYS, null, values);
+ // TODO: this is wrong:
rowUri = Keys.buildPublicKeysUri(Long.toString(rowId));
sendBroadcastDatabaseChange(getKeyType(match), getType(uri));
break;
case PUBLIC_KEY_RING_USER_ID:
rowId = db.insertOrThrow(Tables.USER_IDS, null, values);
+ // TODO: this is wrong:
rowUri = UserIds.buildPublicUserIdsUri(Long.toString(rowId));
sendBroadcastDatabaseChange(getKeyType(match), getType(uri));
@@ -757,18 +780,33 @@ public class KeychainProvider extends ContentProvider {
values.put(Keys.TYPE, KeyTypes.SECRET);
rowId = db.insertOrThrow(Tables.KEYS, null, values);
+ // TODO: this is wrong:
rowUri = Keys.buildSecretKeysUri(Long.toString(rowId));
sendBroadcastDatabaseChange(getKeyType(match), getType(uri));
break;
case SECRET_KEY_RING_USER_ID:
rowId = db.insertOrThrow(Tables.USER_IDS, null, values);
+ // TODO: this is wrong:
rowUri = UserIds.buildSecretUserIdsUri(Long.toString(rowId));
break;
case API_APPS:
rowId = db.insertOrThrow(Tables.API_APPS, null, values);
- rowUri = ApiApps.buildIdUri(Long.toString(rowId));
+// rowUri = ApiApps.buildIdUri(Long.toString(rowId));
+
+ break;
+ case API_ACCOUNTS:
+ // set foreign key automatically based on given uri
+ // e.g., api_apps/com.example.app/accounts/
+ String packageName = uri.getPathSegments().get(1);
+ values.put(ApiAccounts.PACKAGE_NAME_FK, packageName);
+
+ Log.d(Constants.TAG, "provider packageName: " + packageName);
+
+ rowId = db.insertOrThrow(Tables.API_ACCOUNTS, null, values);
+ // TODO: this is wrong:
+// rowUri = ApiAccounts.buildIdUri(Long.toString(rowId));
break;
default:
@@ -828,12 +866,12 @@ public class KeychainProvider extends ContentProvider {
count = db.delete(Tables.KEYS, buildDefaultUserIdsSelection(uri, selection),
selectionArgs);
break;
- case API_APPS_BY_ROW_ID:
- count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, false, selection),
+ case API_APPS_BY_PACKAGE_NAME:
+ count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, selection),
selectionArgs);
break;
- case API_APPS_BY_PACKAGE_NAME:
- count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, true, selection),
+ case API_ACCOUNTS_BY_ACCOUNT_NAME:
+ count = db.delete(Tables.API_ACCOUNTS, buildDefaultApiAccountsSelection(uri, selection),
selectionArgs);
break;
default:
@@ -898,13 +936,13 @@ public class KeychainProvider extends ContentProvider {
count = db.update(Tables.USER_IDS, values,
buildDefaultUserIdsSelection(uri, selection), selectionArgs);
break;
- case API_APPS_BY_ROW_ID:
- count = db.update(Tables.API_APPS, values,
- buildDefaultApiAppsSelection(uri, false, selection), selectionArgs);
- break;
case API_APPS_BY_PACKAGE_NAME:
count = db.update(Tables.API_APPS, values,
- buildDefaultApiAppsSelection(uri, true, selection), selectionArgs);
+ buildDefaultApiAppsSelection(uri, selection), selectionArgs);
+ break;
+ case API_ACCOUNTS_BY_ACCOUNT_NAME:
+ count = db.update(Tables.API_ACCOUNTS, values,
+ buildDefaultApiAccountsSelection(uri, selection), selectionArgs);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
@@ -1003,19 +1041,29 @@ public class KeychainProvider extends ContentProvider {
* @param selection
* @return
*/
- private String buildDefaultApiAppsSelection(Uri uri, boolean packageSelection, String selection) {
- String lastPathSegment = uri.getLastPathSegment();
+ private String buildDefaultApiAppsSelection(Uri uri, String selection) {
+ String packageName = DatabaseUtils.sqlEscapeString(uri.getLastPathSegment());
String andSelection = "";
if (!TextUtils.isEmpty(selection)) {
andSelection = " AND (" + selection + ")";
}
- if (packageSelection) {
- return ApiApps.PACKAGE_NAME + "=" + lastPathSegment + andSelection;
- } else {
- return BaseColumns._ID + "=" + lastPathSegment + andSelection;
+ return ApiApps.PACKAGE_NAME + "=" + packageName + andSelection;
+ }
+
+ private String buildDefaultApiAccountsSelection(Uri uri, String selection) {
+ String packageName = DatabaseUtils.sqlEscapeString(uri.getPathSegments().get(1));
+ String accountName = DatabaseUtils.sqlEscapeString(uri.getLastPathSegment());
+
+ String andSelection = "";
+ if (!TextUtils.isEmpty(selection)) {
+ andSelection = " AND (" + selection + ")";
}
+
+ return ApiAccounts.PACKAGE_NAME_FK + "=" + packageName + " AND "
+ + ApiAccounts.ACCOUNT_NAME + "=" + accountName
+ + andSelection;
}
// @Override
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 2fa903fe2..71f74b8d8 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -22,6 +22,7 @@ import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.RemoteException;
+
import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.openpgp.*;
import org.sufficientlysecure.keychain.Constants;
@@ -33,7 +34,8 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
-import org.sufficientlysecure.keychain.service.remote.AppSettings;
+import org.sufficientlysecure.keychain.remote.AccountSettings;
+import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
@@ -469,11 +471,11 @@ public class ProviderHelper {
cr.delete(KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)), null, null);
}
- public static void deleteUnifiedKeyRing(Context context,String masterKeyId,boolean isSecretKey){
- ContentResolver cr= context.getContentResolver();
- cr.delete(KeyRings.buildPublicKeyRingsByMasterKeyIdUri(masterKeyId),null,null);
- if(isSecretKey){
- cr.delete(KeyRings.buildSecretKeyRingsByMasterKeyIdUri(masterKeyId),null,null);
+ public static void deleteUnifiedKeyRing(Context context, String masterKeyId, boolean isSecretKey) {
+ ContentResolver cr = context.getContentResolver();
+ cr.delete(KeyRings.buildPublicKeyRingsByMasterKeyIdUri(masterKeyId), null, null);
+ if (isSecretKey) {
+ cr.delete(KeyRings.buildSecretKeyRingsByMasterKeyIdUri(masterKeyId), null, null);
}
}
@@ -504,7 +506,7 @@ public class ProviderHelper {
+ " AS sign_keys WHERE sign_keys." + Keys.KEY_RING_ROW_ID + " = "
+ KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID
+ " AND sign_keys." + Keys.CAN_SIGN + " = '1' AND " + Keys.IS_MASTER_KEY
- + " = 1) AS sign", };
+ + " = 1) AS sign",};
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(queryUri, projection, null, null, null);
@@ -801,19 +803,28 @@ public class ProviderHelper {
ContentValues values = new ContentValues();
values.put(ApiApps.PACKAGE_NAME, appSettings.getPackageName());
values.put(ApiApps.PACKAGE_SIGNATURE, appSettings.getPackageSignature());
- values.put(ApiApps.KEY_ID, appSettings.getKeyId());
- values.put(ApiApps.COMPRESSION, appSettings.getCompression());
- values.put(ApiApps.ENCRYPTION_ALGORITHM, appSettings.getEncryptionAlgorithm());
- values.put(ApiApps.HASH_ALORITHM, appSettings.getHashAlgorithm());
+ return values;
+ }
+ private static ContentValues contentValueForApiAccounts(AccountSettings accSettings) {
+ ContentValues values = new ContentValues();
+ values.put(KeychainContract.ApiAccounts.ACCOUNT_NAME, accSettings.getAccountName());
+ values.put(KeychainContract.ApiAccounts.KEY_ID, accSettings.getKeyId());
+ values.put(KeychainContract.ApiAccounts.COMPRESSION, accSettings.getCompression());
+ values.put(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM, accSettings.getEncryptionAlgorithm());
+ values.put(KeychainContract.ApiAccounts.HASH_ALORITHM, accSettings.getHashAlgorithm());
return values;
}
public static void insertApiApp(Context context, AppSettings appSettings) {
- context.getContentResolver().insert(ApiApps.CONTENT_URI,
+ context.getContentResolver().insert(KeychainContract.ApiApps.CONTENT_URI,
contentValueForApiApps(appSettings));
}
+ public static void insertApiAccount(Context context, Uri uri, AccountSettings accSettings) {
+ context.getContentResolver().insert(uri, contentValueForApiAccounts(accSettings));
+ }
+
public static void updateApiApp(Context context, AppSettings appSettings, Uri uri) {
if (context.getContentResolver().update(uri, contentValueForApiApps(appSettings), null,
null) <= 0) {
@@ -821,30 +832,59 @@ public class ProviderHelper {
}
}
+ public static void updateApiAccount(Context context, AccountSettings accSettings, Uri uri) {
+ if (context.getContentResolver().update(uri, contentValueForApiAccounts(accSettings), null,
+ null) <= 0) {
+ throw new RuntimeException();
+ }
+ }
+
+ /**
+ * Must be an uri pointing to an account
+ *
+ * @param context
+ * @param uri
+ * @return
+ */
public static AppSettings getApiAppSettings(Context context, Uri uri) {
AppSettings settings = null;
Cursor cur = context.getContentResolver().query(uri, null, null, null, null);
if (cur != null && cur.moveToFirst()) {
settings = new AppSettings();
- settings.setPackageName(cur.getString(cur
- .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)));
- settings.setPackageSignature(cur.getBlob(cur
- .getColumnIndex(KeychainContract.ApiApps.PACKAGE_SIGNATURE)));
- settings.setKeyId(cur.getLong(cur.getColumnIndex(KeychainContract.ApiApps.KEY_ID)));
- settings.setCompression(cur.getInt(cur
- .getColumnIndexOrThrow(KeychainContract.ApiApps.COMPRESSION)));
- settings.setHashAlgorithm(cur.getInt(cur
- .getColumnIndexOrThrow(KeychainContract.ApiApps.HASH_ALORITHM)));
- settings.setEncryptionAlgorithm(cur.getInt(cur
- .getColumnIndexOrThrow(KeychainContract.ApiApps.ENCRYPTION_ALGORITHM)));
+ settings.setPackageName(cur.getString(
+ cur.getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)));
+ settings.setPackageSignature(cur.getBlob(
+ cur.getColumnIndex(KeychainContract.ApiApps.PACKAGE_SIGNATURE)));
+ }
+
+ return settings;
+ }
+
+ public static AccountSettings getApiAccountSettings(Context context, Uri uri) {
+ AccountSettings settings = null;
+
+ Cursor cur = context.getContentResolver().query(uri, null, null, null, null);
+ if (cur != null && cur.moveToFirst()) {
+ settings = new AccountSettings();
+
+ settings.setAccountName(cur.getString(
+ cur.getColumnIndex(KeychainContract.ApiAccounts.ACCOUNT_NAME)));
+ settings.setKeyId(cur.getLong(
+ cur.getColumnIndex(KeychainContract.ApiAccounts.KEY_ID)));
+ settings.setCompression(cur.getInt(
+ cur.getColumnIndexOrThrow(KeychainContract.ApiAccounts.COMPRESSION)));
+ settings.setHashAlgorithm(cur.getInt(
+ cur.getColumnIndexOrThrow(KeychainContract.ApiAccounts.HASH_ALORITHM)));
+ settings.setEncryptionAlgorithm(cur.getInt(
+ cur.getColumnIndexOrThrow(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM)));
}
return settings;
}
public static byte[] getApiAppSignature(Context context, String packageName) {
- Uri queryUri = KeychainContract.ApiApps.buildByPackageNameUri(packageName);
+ Uri queryUri = ApiApps.buildByPackageNameUri(packageName);
String[] projection = new String[]{ApiApps.PACKAGE_SIGNATURE};
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettings.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/AccountSettings.java
index 6f2d67efb..832cbc752 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettings.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/AccountSettings.java
@@ -15,48 +15,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.Id;
-public class AppSettings {
- private String mPackageName;
- private byte[] mPackageSignature;
+public class AccountSettings {
+ private String mAccountName;
private long mKeyId = Id.key.none;
private int mEncryptionAlgorithm;
private int mHashAlgorithm;
private int mCompression;
- public AppSettings() {
+ public AccountSettings() {
}
- public AppSettings(String packageName, byte[] packageSignature) {
+ public AccountSettings(String accountName) {
super();
- this.mPackageName = packageName;
- this.mPackageSignature = packageSignature;
+ this.mAccountName = accountName;
+
// defaults:
this.mEncryptionAlgorithm = PGPEncryptedData.AES_256;
this.mHashAlgorithm = HashAlgorithmTags.SHA512;
this.mCompression = Id.choice.compression.zlib;
}
- public String getPackageName() {
- return mPackageName;
- }
-
- public void setPackageName(String packageName) {
- this.mPackageName = packageName;
- }
-
- public byte[] getPackageSignature() {
- return mPackageSignature;
+ public String getAccountName() {
+ return mAccountName;
}
- public void setPackageSignature(byte[] packageSignature) {
- this.mPackageSignature = packageSignature;
+ public void setAccountName(String mAccountName) {
+ this.mAccountName = mAccountName;
}
public long getKeyId() {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/AppSettings.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/AppSettings.java
new file mode 100644
index 000000000..6c7e51bf0
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/AppSettings.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.remote;
+
+import org.spongycastle.bcpg.HashAlgorithmTags;
+import org.spongycastle.openpgp.PGPEncryptedData;
+import org.sufficientlysecure.keychain.Id;
+
+public class AppSettings {
+ private String mPackageName;
+ private byte[] mPackageSignature;
+
+ public AppSettings() {
+
+ }
+
+ public AppSettings(String packageName, byte[] packageSignature) {
+ super();
+ this.mPackageName = packageName;
+ this.mPackageSignature = packageSignature;
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ public void setPackageName(String packageName) {
+ this.mPackageName = packageName;
+ }
+
+ public byte[] getPackageSignature() {
+ return mPackageSignature;
+ }
+
+ public void setPackageSignature(byte[] packageSignature) {
+ this.mPackageSignature = packageSignature;
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
index 95dc897f0..fa6ccf63b 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote;
import android.app.PendingIntent;
import android.content.Intent;
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
@@ -137,7 +138,7 @@ public class OpenPgpService extends RemoteService {
}
private Intent signImpl(Intent data, ParcelFileDescriptor input,
- ParcelFileDescriptor output, AppSettings appSettings) {
+ ParcelFileDescriptor output, AccountSettings accSettings) {
try {
boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
@@ -146,11 +147,11 @@ public class OpenPgpService extends RemoteService {
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
} else {
- passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId());
+ passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), accSettings.getKeyId());
}
if (passphrase == null) {
// get PendingIntent for passphrase input, add it to given params and return to client
- Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId());
+ Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());
return passphraseBundle;
}
@@ -164,9 +165,9 @@ public class OpenPgpService extends RemoteService {
// sign-only
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(getContext(), inputData, os);
builder.enableAsciiArmorOutput(asciiArmor)
- .signatureHashAlgorithm(appSettings.getHashAlgorithm())
+ .signatureHashAlgorithm(accSettings.getHashAlgorithm())
.signatureForceV3(false)
- .signatureKeyId(appSettings.getKeyId())
+ .signatureKeyId(accSettings.getKeyId())
.signaturePassphrase(passphrase);
builder.build().execute();
} finally {
@@ -187,7 +188,7 @@ public class OpenPgpService extends RemoteService {
}
private Intent encryptAndSignImpl(Intent data, ParcelFileDescriptor input,
- ParcelFileDescriptor output, AppSettings appSettings, boolean sign) {
+ ParcelFileDescriptor output, AccountSettings accSettings, boolean sign) {
try {
boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
@@ -217,7 +218,7 @@ public class OpenPgpService extends RemoteService {
// add own key for encryption
keyIds = Arrays.copyOf(keyIds, keyIds.length + 1);
- keyIds[keyIds.length - 1] = appSettings.getKeyId();
+ keyIds[keyIds.length - 1] = accSettings.getKeyId();
// build InputData and write into OutputStream
// Get Input- and OutputStream from ParcelFileDescriptor
@@ -229,8 +230,8 @@ public class OpenPgpService extends RemoteService {
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(getContext(), inputData, os);
builder.enableAsciiArmorOutput(asciiArmor)
- .compressionId(appSettings.getCompression())
- .symmetricEncryptionAlgorithm(appSettings.getEncryptionAlgorithm())
+ .compressionId(accSettings.getCompression())
+ .symmetricEncryptionAlgorithm(accSettings.getEncryptionAlgorithm())
.encryptionKeyIds(keyIds);
if (sign) {
@@ -239,18 +240,18 @@ public class OpenPgpService extends RemoteService {
passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
} else {
passphrase = PassphraseCacheService.getCachedPassphrase(getContext(),
- appSettings.getKeyId());
+ accSettings.getKeyId());
}
if (passphrase == null) {
// get PendingIntent for passphrase input, add it to given params and return to client
- Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId());
+ Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());
return passphraseBundle;
}
// sign and encrypt
- builder.signatureHashAlgorithm(appSettings.getHashAlgorithm())
+ builder.signatureHashAlgorithm(accSettings.getHashAlgorithm())
.signatureForceV3(false)
- .signatureKeyId(appSettings.getKeyId())
+ .signatureKeyId(accSettings.getKeyId())
.signaturePassphrase(passphrase);
} else {
// encrypt only
@@ -276,7 +277,7 @@ public class OpenPgpService extends RemoteService {
}
private Intent decryptAndVerifyImpl(Intent data, ParcelFileDescriptor input,
- ParcelFileDescriptor output, AppSettings appSettings) {
+ ParcelFileDescriptor output, AccountSettings accSettings) {
try {
// Get Input- and OutputStream from ParcelFileDescriptor
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
@@ -292,7 +293,7 @@ public class OpenPgpService extends RemoteService {
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os);
builder.assumeSymmetric(false) // no support for symmetric encryption
// allow only the private key for this app for decryption
- .enforcedKeyId(appSettings.getKeyId())
+ .enforcedKeyId(accSettings.getKeyId())
.passphrase(passphrase);
// TODO: currently does not support binary signed-only content
@@ -300,7 +301,7 @@ public class OpenPgpService extends RemoteService {
if (decryptVerifyResult.isKeyPassphraseNeeded()) {
// get PendingIntent for passphrase input, add it to given params and return to client
- Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId());
+ Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());
return passphraseBundle;
} else if (decryptVerifyResult.isSymmetricPassphraseNeeded()) {
throw new PgpGeneralException("Decryption of symmetric content not supported by API!");
@@ -432,17 +433,26 @@ public class OpenPgpService extends RemoteService {
return errorResult;
}
- final AppSettings appSettings = getAppSettings();
+ String accName;
+ if (data.getStringExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME) != null) {
+ accName = data.getStringExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME);
+ } else {
+ accName = "default";
+ }
+ final AccountSettings accSettings = getAccSettings(accName);
+ if (accSettings == null) {
+ return getCreateAccountIntent(data, accName);
+ }
String action = data.getAction();
if (OpenPgpApi.ACTION_SIGN.equals(action)) {
- return signImpl(data, input, output, appSettings);
+ return signImpl(data, input, output, accSettings);
} else if (OpenPgpApi.ACTION_ENCRYPT.equals(action)) {
- return encryptAndSignImpl(data, input, output, appSettings, false);
+ return encryptAndSignImpl(data, input, output, accSettings, false);
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(action)) {
- return encryptAndSignImpl(data, input, output, appSettings, true);
+ return encryptAndSignImpl(data, input, output, accSettings, true);
} else if (OpenPgpApi.ACTION_DECRYPT_VERIFY.equals(action)) {
- return decryptAndVerifyImpl(data, input, output, appSettings);
+ return decryptAndVerifyImpl(data, input, output, accSettings);
} else if (OpenPgpApi.ACTION_GET_KEY.equals(action)) {
return getKeyImpl(data);
} else if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(action)) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java
index 6a883316a..7e935d317 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java
@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote;
import android.app.PendingIntent;
import android.app.Service;
@@ -27,12 +27,14 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.net.Uri;
import android.os.Binder;
+
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
@@ -47,7 +49,6 @@ public abstract class RemoteService extends Service {
private static final int PRIVATE_REQUEST_CODE_REGISTER = 651;
private static final int PRIVATE_REQUEST_CODE_ERROR = 652;
-
public Context getContext() {
return mContext;
}
@@ -55,13 +56,9 @@ public abstract class RemoteService extends Service {
protected Intent isAllowed(Intent data) {
try {
if (isCallerAllowed(false)) {
-
return null;
} else {
- String[] callingPackages = getPackageManager().getPackagesForUid(
- Binder.getCallingUid());
- // TODO: currently simply uses first entry
- String packageName = callingPackages[0];
+ String packageName = getCurrentCallingPackage();
byte[] packageSignature;
try {
@@ -84,7 +81,7 @@ public abstract class RemoteService extends Service {
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(),
- PRIVATE_REQUEST_CODE_REGISTER, intent, 0);
+ PRIVATE_REQUEST_CODE_REGISTER, intent, 0);
// return PendingIntent to be executed by client
Intent result = new Intent();
@@ -99,11 +96,11 @@ public abstract class RemoteService extends Service {
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE);
intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
- getString(R.string.api_error_wrong_signature));
+ getString(R.string.api_error_wrong_signature));
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(),
- PRIVATE_REQUEST_CODE_ERROR, intent, 0);
+ PRIVATE_REQUEST_CODE_ERROR, intent, 0);
// return PendingIntent to be executed by client
Intent result = new Intent();
@@ -125,27 +122,56 @@ public abstract class RemoteService extends Service {
}
/**
- * Retrieves AppSettings from database for the application calling this remote service
+ * Returns package name associated with the UID, which is assigned to the process that sent you the
+ * current transaction that is being processed :)
*
- * @return
+ * @return package name
*/
- protected AppSettings getAppSettings() {
+ private String getCurrentCallingPackage() {
+ // TODO:
+ // callingPackages contains more than one entry when sharedUserId has been used...
String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
+ String currentPkg = callingPackages[0];
+ Log.d(Constants.TAG, "currentPkg: " + currentPkg);
- // get app settings for this package
- for (int i = 0; i < callingPackages.length; i++) {
- String currentPkg = callingPackages[i];
+ return currentPkg;
+ }
- Uri uri = KeychainContract.ApiApps.buildByPackageNameUri(currentPkg);
+ /**
+ * Retrieves AccountSettings from database for the application calling this remote service
+ *
+ * @return
+ */
+ protected AccountSettings getAccSettings(String accountName) {
+ String currentPkg = getCurrentCallingPackage();
+ Log.d(Constants.TAG, "accountName: " + accountName);
- AppSettings settings = ProviderHelper.getApiAppSettings(this, uri);
+ Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(currentPkg, accountName);
- if (settings != null) {
- return settings;
- }
- }
+ AccountSettings settings = ProviderHelper.getApiAccountSettings(this, uri);
+
+ return settings; // can be null!
+ }
+
+ protected Intent getCreateAccountIntent(Intent data, String accountName) {
+ String packageName = getCurrentCallingPackage();
+ Log.d(Constants.TAG, "accountName: " + accountName);
+
+ Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
+ intent.setAction(RemoteServiceActivity.ACTION_CREATE_ACCOUNT);
+ intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
+ intent.putExtra(RemoteServiceActivity.EXTRA_ACC_NAME, accountName);
+ intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
+
+ PendingIntent pi = PendingIntent.getActivity(getBaseContext(),
+ PRIVATE_REQUEST_CODE_REGISTER, intent, 0);
+
+ // return PendingIntent to be executed by client
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
- return null;
+ return result;
}
/**
@@ -216,7 +242,7 @@ public abstract class RemoteService extends Service {
return true;
} else {
throw new WrongPackageSignatureException(
- "PACKAGE NOT ALLOWED! Signature wrong! (Signature not equals signature from database)");
+ "PACKAGE NOT ALLOWED! Signature wrong! (Signature not equals signature from database)");
}
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/WrongPackageSignatureException.java
index 0b642086a..6f44a65e9 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/WrongPackageSignatureException.java
@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote;
public class WrongPackageSignatureException extends Exception {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
index 52b06a2ae..3d88d216e 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote.ui;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -35,6 +35,8 @@ import android.widget.TextView;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.remote.AccountSettings;
+import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter;
import org.sufficientlysecure.keychain.util.AlgorithmNames;
@@ -43,11 +45,11 @@ import org.sufficientlysecure.keychain.util.Log;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-public class AppSettingsFragment extends Fragment implements
+public class AccountSettingsFragment extends Fragment implements
SelectSecretKeyLayoutFragment.SelectSecretKeyCallback {
// model
- private AppSettings mAppSettings;
+ private AccountSettings mAccSettings;
// view
private TextView mAppNameView;
@@ -64,25 +66,25 @@ public class AppSettingsFragment extends Fragment implements
KeyValueSpinnerAdapter mHashAdapter;
KeyValueSpinnerAdapter mCompressionAdapter;
- public AppSettings getAppSettings() {
- return mAppSettings;
+ public AccountSettings getAccSettings() {
+ return mAccSettings;
}
- public void setAppSettings(AppSettings appSettings) {
- this.mAppSettings = appSettings;
- setPackage(appSettings.getPackageName());
- mPackageName.setText(appSettings.getPackageName());
-
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-256");
- md.update(appSettings.getPackageSignature());
- byte[] digest = md.digest();
- String signature = new String(Hex.encode(digest));
-
- mPackageSignature.setText(signature);
- } catch (NoSuchAlgorithmException e) {
- Log.e(Constants.TAG, "Should not happen!", e);
- }
+ public void setAccSettings(AccountSettings appSettings) {
+ this.mAccSettings = appSettings;
+// setPackage(appSettings.getPackageName());
+// mPackageName.setText(appSettings.getPackageName());
+
+// try {
+// MessageDigest md = MessageDigest.getInstance("SHA-256");
+// md.update(appSettings.getPackageSignature());
+// byte[] digest = md.digest();
+// String signature = new String(Hex.encode(digest));
+//
+// mPackageSignature.setText(signature);
+// } catch (NoSuchAlgorithmException e) {
+// Log.e(Constants.TAG, "Should not happen!", e);
+// }
mSelectKeyFragment.selectKey(appSettings.getKeyId());
mEncryptionAlgorithm.setSelection(mEncryptionAdapter.getPosition(appSettings
@@ -96,7 +98,7 @@ public class AppSettingsFragment extends Fragment implements
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.api_app_settings_fragment, container, false);
+ View view = inflater.inflate(R.layout.api_account_settings_fragment, container, false);
initView(view);
return view;
}
@@ -112,17 +114,17 @@ public class AppSettingsFragment extends Fragment implements
private void initView(View view) {
mSelectKeyFragment = (SelectSecretKeyLayoutFragment) getFragmentManager().findFragmentById(
- R.id.api_app_settings_select_key_fragment);
+ R.id.api_account_settings_select_key_fragment);
mSelectKeyFragment.setCallback(this);
- mAppNameView = (TextView) view.findViewById(R.id.api_app_settings_app_name);
- mAppIconView = (ImageView) view.findViewById(R.id.api_app_settings_app_icon);
+ mAppNameView = (TextView) view.findViewById(R.id.api_account_settings_app_name);
+ mAppIconView = (ImageView) view.findViewById(R.id.api_account_settings_app_icon);
mEncryptionAlgorithm = (Spinner) view
- .findViewById(R.id.api_app_settings_encryption_algorithm);
- mHashAlgorithm = (Spinner) view.findViewById(R.id.api_app_settings_hash_algorithm);
- mCompression = (Spinner) view.findViewById(R.id.api_app_settings_compression);
- mPackageName = (TextView) view.findViewById(R.id.api_app_settings_package_name);
- mPackageSignature = (TextView) view.findViewById(R.id.api_app_settings_package_signature);
+ .findViewById(R.id.api_account_settings_encryption_algorithm);
+ mHashAlgorithm = (Spinner) view.findViewById(R.id.api_account_settings_hash_algorithm);
+ mCompression = (Spinner) view.findViewById(R.id.api_account_settings_compression);
+ mPackageName = (TextView) view.findViewById(R.id.api_account_settings_package_name);
+ mPackageSignature = (TextView) view.findViewById(R.id.api_account_settings_package_signature);
AlgorithmNames algorithmNames = new AlgorithmNames(getActivity());
@@ -133,7 +135,7 @@ public class AppSettingsFragment extends Fragment implements
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- mAppSettings.setEncryptionAlgorithm((int) id);
+ mAccSettings.setEncryptionAlgorithm((int) id);
}
@Override
@@ -147,7 +149,7 @@ public class AppSettingsFragment extends Fragment implements
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- mAppSettings.setHashAlgorithm((int) id);
+ mAccSettings.setHashAlgorithm((int) id);
}
@Override
@@ -162,7 +164,7 @@ public class AppSettingsFragment extends Fragment implements
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- mAppSettings.setCompression((int) id);
+ mAccSettings.setCompression((int) id);
}
@Override
@@ -170,32 +172,32 @@ public class AppSettingsFragment extends Fragment implements
}
});
}
-
- private void setPackage(String packageName) {
- PackageManager pm = getActivity().getApplicationContext().getPackageManager();
-
- // get application name and icon from package manager
- String appName = null;
- Drawable appIcon = null;
- try {
- ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
-
- appName = (String) pm.getApplicationLabel(ai);
- appIcon = pm.getApplicationIcon(ai);
- } catch (final NameNotFoundException e) {
- // fallback
- appName = packageName;
- }
- mAppNameView.setText(appName);
- mAppIconView.setImageDrawable(appIcon);
- }
+//
+// private void setPackage(String packageName) {
+// PackageManager pm = getActivity().getApplicationContext().getPackageManager();
+//
+// // get application name and icon from package manager
+// String appName = null;
+// Drawable appIcon = null;
+// try {
+// ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
+//
+// appName = (String) pm.getApplicationLabel(ai);
+// appIcon = pm.getApplicationIcon(ai);
+// } catch (final NameNotFoundException e) {
+// // fallback
+// appName = packageName;
+// }
+// mAppNameView.setText(appName);
+// mAppIconView.setImageDrawable(appIcon);
+// }
/**
* callback from select secret key fragment
*/
@Override
public void onKeySelected(long secretKeyId) {
- mAppSettings.setKeyId(secretKeyId);
+ mAccSettings.setKeyId(secretKeyId);
}
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountsListFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountsListFragment.java
new file mode 100644
index 000000000..853dc2d3c
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountsListFragment.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.remote.ui;
+
+import android.annotation.TargetApi;
+import android.content.ContentUris;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.SimpleCursorAdapter;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
+
+// TODO: make compat with < 11
+@TargetApi(Build.VERSION_CODES.HONEYCOMB)
+public class AccountsListFragment extends ListFragment implements
+ LoaderManager.LoaderCallbacks<Cursor> {
+
+ private static final String ARG_DATA_URI = "uri";
+
+ // This is the Adapter being used to display the list's data.
+ SimpleCursorAdapter mAdapter;
+
+ private Uri mDataUri;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static AccountsListFragment newInstance(Uri dataUri) {
+ AccountsListFragment frag = new AccountsListFragment();
+
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_DATA_URI, dataUri);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mDataUri = getArguments().getParcelable(ARG_DATA_URI);
+
+ getListView().setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
+// // edit app settings
+// Intent intent = new Intent(getActivity(), AppSettingsActivity.class);
+// intent.setData(ContentUris.withAppendedId(ApiApps.CONTENT_URI, id));
+// startActivity(intent);
+ }
+ });
+
+ // Give some text to display if there is no data. In a real
+ // application this would come from a resource.
+ setEmptyText(getString(R.string.api_settings_accounts_empty));
+
+ // We have a menu item to show in action bar.
+ setHasOptionsMenu(true);
+
+ // Create an empty adapter we will use to display the loaded data.
+ mAdapter = new SimpleCursorAdapter(getActivity(),
+ android.R.layout.simple_list_item_1,
+ null,
+ new String[]{KeychainContract.ApiAccounts.ACCOUNT_NAME},
+ new int[]{android.R.id.text1},
+ 0);
+ setListAdapter(mAdapter);
+
+ // Prepare the loader. Either re-connect with an existing one,
+ // or start a new one.
+ getLoaderManager().initLoader(0, null, this);
+ }
+
+ // These are the Contacts rows that we will retrieve.
+ static final String[] PROJECTION = new String[]{
+ KeychainContract.ApiAccounts._ID,
+ KeychainContract.ApiAccounts.ACCOUNT_NAME};
+
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ // This is called when a new Loader needs to be created. This
+ // sample only has one Loader, so we don't care about the ID.
+ // First, pick the base URI to use depending on whether we are
+ // currently filtering.
+// Uri baseUri = KeychainContract.ApiAccounts.buildBaseUri(mPackageName);
+
+ // Now create and return a CursorLoader that will take care of
+ // creating a Cursor for the data being displayed.
+ return new CursorLoader(getActivity(), mDataUri, PROJECTION, null, null,
+ KeychainContract.ApiAccounts.ACCOUNT_NAME + " COLLATE LOCALIZED ASC");
+ }
+
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ // Swap the new cursor in. (The framework will take care of closing the
+ // old cursor once we return.)
+ mAdapter.swapCursor(data);
+ }
+
+ public void onLoaderReset(Loader<Cursor> loader) {
+ // This is called when the last Cursor provided to onLoadFinished()
+ // above is about to be closed. We need to make sure we are no
+ // longer using it.
+ mAdapter.swapCursor(null);
+ }
+
+// private class RegisteredAppsAdapter extends CursorAdapter {
+//
+// private LayoutInflater mInflater;
+// private PackageManager mPM;
+//
+// public RegisteredAppsAdapter(Context context, Cursor c, int flags) {
+// super(context, c, flags);
+//
+// mInflater = LayoutInflater.from(context);
+// mPM = context.getApplicationContext().getPackageManager();
+// }
+//
+// @Override
+// public void bindView(View view, Context context, Cursor cursor) {
+// TextView text = (TextView) view.findViewById(R.id.api_apps_adapter_item_name);
+// ImageView icon = (ImageView) view.findViewById(R.id.api_apps_adapter_item_icon);
+//
+// String packageName = cursor.getString(cursor.getColumnIndex(ApiApps.PACKAGE_NAME));
+// if (packageName != null) {
+// // get application name
+// try {
+// ApplicationInfo ai = mPM.getApplicationInfo(packageName, 0);
+//
+// text.setText(mPM.getApplicationLabel(ai));
+// icon.setImageDrawable(mPM.getApplicationIcon(ai));
+// } catch (final PackageManager.NameNotFoundException e) {
+// // fallback
+// text.setText(packageName);
+// }
+// } else {
+// // fallback
+// text.setText(packageName);
+// }
+//
+// }
+//
+// @Override
+// public View newView(Context context, Cursor cursor, ViewGroup parent) {
+// return mInflater.inflate(R.layout.api_apps_adapter_list_item, null);
+// }
+// }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java
index 2ef170dec..33cde49ba 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java
@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote.ui;
import android.content.Intent;
import android.net.Uri;
@@ -24,16 +24,20 @@ import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.util.Log;
public class AppSettingsActivity extends ActionBarActivity {
private Uri mAppUri;
private AppSettingsFragment mSettingsFragment;
+ private AccountsListFragment mAccountsListFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -63,7 +67,7 @@ public class AppSettingsActivity extends ActionBarActivity {
return;
} else {
Log.d(Constants.TAG, "uri: " + mAppUri);
- loadData(mAppUri);
+ loadData(savedInstanceState, mAppUri);
}
}
@@ -87,9 +91,34 @@ public class AppSettingsActivity extends ActionBarActivity {
return super.onOptionsItemSelected(item);
}
- private void loadData(Uri appUri) {
+ private void loadData(Bundle savedInstanceState, Uri appUri) {
+ // TODO: load this also like other fragment with newInstance arguments?
AppSettings settings = ProviderHelper.getApiAppSettings(this, appUri);
mSettingsFragment.setAppSettings(settings);
+
+ Uri accountsUri = appUri.buildUpon().appendPath(KeychainContract.PATH_ACCOUNTS).build();
+ Log.d(Constants.TAG, "accountsUri: " + accountsUri);
+ startListFragment(savedInstanceState, accountsUri);
+ }
+
+ private void startListFragment(Bundle savedInstanceState, Uri dataUri) {
+ // However, if we're being restored from a previous state,
+ // then we don't need to do anything and should return or else
+ // we could end up with overlapping fragments.
+ if (savedInstanceState != null) {
+ return;
+ }
+
+ // Create an instance of the fragment
+ mAccountsListFragment = AccountsListFragment.newInstance(dataUri);
+
+ // Add the fragment to the 'fragment_container' FrameLayout
+ // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.api_accounts_list_fragment, mAccountsListFragment)
+ .commitAllowingStateLoss();
+ // do it immediately!
+ getSupportFragmentManager().executePendingTransactions();
}
private void revokeAccess() {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsFragment.java
new file mode 100644
index 000000000..8bcd83fc7
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsFragment.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.remote.ui;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ImageView;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import org.spongycastle.util.encoders.Hex;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.remote.AppSettings;
+import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
+import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter;
+import org.sufficientlysecure.keychain.util.AlgorithmNames;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class AppSettingsFragment extends Fragment {
+
+ // model
+ private AppSettings mAppSettings;
+
+ // view
+ private TextView mAppNameView;
+ private ImageView mAppIconView;
+ private TextView mPackageName;
+ private TextView mPackageSignature;
+
+ public AppSettings getAppSettings() {
+ return mAppSettings;
+ }
+
+ public void setAppSettings(AppSettings appSettings) {
+ this.mAppSettings = appSettings;
+ setPackage(appSettings.getPackageName());
+ mPackageName.setText(appSettings.getPackageName());
+
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ md.update(appSettings.getPackageSignature());
+ byte[] digest = md.digest();
+ String signature = new String(Hex.encode(digest));
+
+ mPackageSignature.setText(signature);
+ } catch (NoSuchAlgorithmException e) {
+ Log.e(Constants.TAG, "Should not happen!", e);
+ }
+
+ }
+
+ /**
+ * Inflate the layout for this fragment
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.api_app_settings_fragment, container, false);
+ initView(view);
+ return view;
+ }
+
+
+ private void initView(View view) {
+ mAppNameView = (TextView) view.findViewById(R.id.api_app_settings_app_name);
+ mAppIconView = (ImageView) view.findViewById(R.id.api_app_settings_app_icon);
+
+ mPackageName = (TextView) view.findViewById(R.id.api_app_settings_package_name);
+ mPackageSignature = (TextView) view.findViewById(R.id.api_app_settings_package_signature);
+ }
+
+ private void setPackage(String packageName) {
+ PackageManager pm = getActivity().getApplicationContext().getPackageManager();
+
+ // get application name and icon from package manager
+ String appName = null;
+ Drawable appIcon = null;
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
+
+ appName = (String) pm.getApplicationLabel(ai);
+ appIcon = pm.getApplicationIcon(ai);
+ } catch (final NameNotFoundException e) {
+ // fallback
+ appName = packageName;
+ }
+ mAppNameView.setText(appName);
+ mAppIconView.setImageDrawable(appIcon);
+ }
+
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java
index f6f216efd..f86d279f0 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java
@@ -15,13 +15,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote.ui;
import android.os.Bundle;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.DrawerActivity;
-public class RegisteredAppsListActivity extends DrawerActivity {
+public class AppsListActivity extends DrawerActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java
index 25d0c7593..f3fa6e7c6 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java
@@ -15,10 +15,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote.ui;
-import android.content.ContentUris;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -26,14 +28,22 @@ import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
+import org.sufficientlysecure.keychain.util.Log;
-public class RegisteredAppsListFragment extends ListFragment implements
+public class AppsListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
// This is the Adapter being used to display the list's data.
@@ -46,9 +56,10 @@ public class RegisteredAppsListFragment extends ListFragment implements
getListView().setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
+ String selectedPackageName = mAdapter.getItemPackageName(position);
// edit app settings
Intent intent = new Intent(getActivity(), AppSettingsActivity.class);
- intent.setData(ContentUris.withAppendedId(KeychainContract.ApiApps.CONTENT_URI, id));
+ intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(selectedPackageName));
startActivity(intent);
}
});
@@ -70,7 +81,10 @@ public class RegisteredAppsListFragment extends ListFragment implements
}
// These are the Contacts rows that we will retrieve.
- static final String[] PROJECTION = new String[]{ApiApps._ID, ApiApps.PACKAGE_NAME};
+ static final String[] PROJECTION = new String[]{
+ ApiApps._ID, // 0
+ ApiApps.PACKAGE_NAME // 1
+ };
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
@@ -98,4 +112,65 @@ public class RegisteredAppsListFragment extends ListFragment implements
mAdapter.swapCursor(null);
}
+ private class RegisteredAppsAdapter extends CursorAdapter {
+
+ private LayoutInflater mInflater;
+ private PackageManager mPM;
+
+ public RegisteredAppsAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+ mPM = context.getApplicationContext().getPackageManager();
+ }
+
+ /**
+ * Similar to CursorAdapter.getItemId().
+ * Required to build Uris for api app view, which is not based on row ids
+ *
+ * @param position
+ * @return
+ */
+ public String getItemPackageName(int position) {
+ if (mDataValid && mCursor != null) {
+ if (mCursor.moveToPosition(position)) {
+ return mCursor.getString(1);
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ TextView text = (TextView) view.findViewById(R.id.api_apps_adapter_item_name);
+ ImageView icon = (ImageView) view.findViewById(R.id.api_apps_adapter_item_icon);
+
+ String packageName = cursor.getString(cursor.getColumnIndex(ApiApps.PACKAGE_NAME));
+ if (packageName != null) {
+ // get application name
+ try {
+ ApplicationInfo ai = mPM.getApplicationInfo(packageName, 0);
+
+ text.setText(mPM.getApplicationLabel(ai));
+ icon.setImageDrawable(mPM.getApplicationIcon(ai));
+ } catch (final PackageManager.NameNotFoundException e) {
+ // fallback
+ text.setText(packageName);
+ }
+ } else {
+ // fallback
+ text.setText(packageName);
+ }
+
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.api_apps_adapter_list_item, null);
+ }
+ }
+
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
index e20114853..d3ac5cade 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.service.remote;
+package org.sufficientlysecure.keychain.remote.ui;
import android.content.Intent;
import android.os.Bundle;
@@ -24,6 +24,7 @@ import android.os.Message;
import android.os.Messenger;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
+
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.htmltextview.HtmlTextView;
import org.sufficientlysecure.keychain.Constants;
@@ -31,7 +32,10 @@ import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.remote.AccountSettings;
+import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
@@ -41,6 +45,8 @@ import java.util.ArrayList;
public class RemoteServiceActivity extends ActionBarActivity {
public static final String ACTION_REGISTER = Constants.INTENT_PREFIX + "API_ACTIVITY_REGISTER";
+ public static final String ACTION_CREATE_ACCOUNT = Constants.INTENT_PREFIX
+ + "API_ACTIVITY_CREATE_ACCOUNT";
public static final String ACTION_CACHE_PASSPHRASE = Constants.INTENT_PREFIX
+ "API_ACTIVITY_CACHE_PASSPHRASE";
public static final String ACTION_SELECT_PUB_KEYS = Constants.INTENT_PREFIX
@@ -57,6 +63,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
// register action
public static final String EXTRA_PACKAGE_NAME = "package_name";
public static final String EXTRA_PACKAGE_SIGNATURE = "package_signature";
+ // create acc action
+ public static final String EXTRA_ACC_NAME = "acc_name";
// select pub keys action
public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids";
public static final String EXTRA_MISSING_USER_IDS = "missing_user_ids";
@@ -65,7 +73,9 @@ public class RemoteServiceActivity extends ActionBarActivity {
public static final String EXTRA_ERROR_MESSAGE = "error_message";
// register view
- private AppSettingsFragment mSettingsFragment;
+ private AppSettingsFragment mAppSettingsFragment;
+ // create acc view
+ private AccountSettingsFragment mAccSettingsFragment;
// select pub keys view
private SelectPublicKeyFragment mSelectFragment;
@@ -94,13 +104,52 @@ public class RemoteServiceActivity extends ActionBarActivity {
public void onClick(View v) {
// Allow
+ ProviderHelper.insertApiApp(RemoteServiceActivity.this,
+ mAppSettingsFragment.getAppSettings());
+
+ // give data through for new service call
+ Intent resultData = extras.getParcelable(EXTRA_DATA);
+ RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
+ RemoteServiceActivity.this.finish();
+ }
+ }, R.string.api_register_disallow, R.drawable.ic_action_cancel,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Disallow
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
+ RemoteServiceActivity.this.finish();
+ }
+ }
+ );
+
+ setContentView(R.layout.api_app_register_activity);
+
+ mAppSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById(
+ R.id.api_app_settings_fragment);
+
+ AppSettings settings = new AppSettings(packageName, packageSignature);
+ mAppSettingsFragment.setAppSettings(settings);
+ } else if (ACTION_CREATE_ACCOUNT.equals(action)) {
+ final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
+ final String accName = extras.getString(EXTRA_ACC_NAME);
+
+ // Inflate a "Done"/"Cancel" custom action bar view
+ ActionBarHelper.setTwoButtonView(getSupportActionBar(),
+ R.string.api_settings_save, R.drawable.ic_action_done,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Save
+
// user needs to select a key!
- if (mSettingsFragment.getAppSettings().getKeyId() == Id.key.none) {
- mSettingsFragment.setErrorOnSelectKeyFragment(
+ if (mAccSettingsFragment.getAccSettings().getKeyId() == Id.key.none) {
+ mAccSettingsFragment.setErrorOnSelectKeyFragment(
getString(R.string.api_register_error_select_key));
} else {
- ProviderHelper.insertApiApp(RemoteServiceActivity.this,
- mSettingsFragment.getAppSettings());
+ ProviderHelper.insertApiAccount(RemoteServiceActivity.this,
+ KeychainContract.ApiAccounts.buildBaseUri(packageName),
+ mAccSettingsFragment.getAccSettings());
// give data through for new service call
Intent resultData = extras.getParcelable(EXTRA_DATA);
@@ -108,24 +157,24 @@ public class RemoteServiceActivity extends ActionBarActivity {
RemoteServiceActivity.this.finish();
}
}
- }, R.string.api_register_disallow, R.drawable.ic_action_cancel,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Disallow
- RemoteServiceActivity.this.setResult(RESULT_CANCELED);
- RemoteServiceActivity.this.finish();
- }
+ }, R.string.api_settings_cancel, R.drawable.ic_action_cancel,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Cancel
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
+ RemoteServiceActivity.this.finish();
+ }
}
);
- setContentView(R.layout.api_app_register_activity);
+ setContentView(R.layout.api_account_create_activity);
- mSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById(
- R.id.api_app_settings_fragment);
+ mAccSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById(
+ R.id.api_account_settings_fragment);
- AppSettings settings = new AppSettings(packageName, packageSignature);
- mSettingsFragment.setAppSettings(settings);
+ AccountSettings settings = new AccountSettings(accName);
+ mAccSettingsFragment.setAccSettings(settings);
} else if (ACTION_CACHE_PASSPHRASE.equals(action)) {
long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID);
Intent resultData = extras.getParcelable(EXTRA_DATA);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java
deleted file mode 100644
index e0dc4162f..000000000
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.database.Cursor;
-import android.support.v4.widget.CursorAdapter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
-
-public class RegisteredAppsAdapter extends CursorAdapter {
-
- private LayoutInflater mInflater;
- private PackageManager mPM;
-
- public RegisteredAppsAdapter(Context context, Cursor c, int flags) {
- super(context, c, flags);
-
- mInflater = LayoutInflater.from(context);
- mPM = context.getApplicationContext().getPackageManager();
- }
-
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- TextView text = (TextView) view.findViewById(R.id.api_apps_adapter_item_name);
- ImageView icon = (ImageView) view.findViewById(R.id.api_apps_adapter_item_icon);
-
- String packageName = cursor.getString(cursor.getColumnIndex(ApiApps.PACKAGE_NAME));
- if (packageName != null) {
- // get application name
- try {
- ApplicationInfo ai = mPM.getApplicationInfo(packageName, 0);
-
- text.setText(mPM.getApplicationLabel(ai));
- icon.setImageDrawable(mPM.getApplicationIcon(ai));
- } catch (final NameNotFoundException e) {
- // fallback
- text.setText(packageName);
- }
- } else {
- // fallback
- text.setText(packageName);
- }
-
- }
-
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(R.layout.api_apps_adapter_list_item, null);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/main/res/layout/api_account_create_activity.xml b/OpenPGP-Keychain/src/main/res/layout/api_account_create_activity.xml
new file mode 100644
index 000000000..ead336dbb
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/res/layout/api_account_create_activity.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="16dp"
+ android:orientation="vertical">
+
+ <fragment
+ android:id="@+id/api_account_settings_fragment"
+ android:name="org.sufficientlysecure.keychain.remote.ui.AccountSettingsFragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ tools:layout="@layout/api_app_settings_fragment" />
+
+ </LinearLayout>
+</ScrollView>
diff --git a/OpenPGP-Keychain/src/main/res/layout/api_account_settings_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/api_account_settings_fragment.xml
new file mode 100644
index 000000000..3284b5b0a
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/res/layout/api_account_settings_fragment.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:custom="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_marginBottom="4dp"
+ android:layout_marginTop="4dp"
+ android:gravity="center_horizontal"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/api_account_settings_app_icon"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginRight="6dp"
+ android:src="@drawable/icon" />
+
+ <TextView
+ android:id="@+id/api_account_settings_app_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toRightOf="@+id/api_app_settings_app_icon"
+ android:gravity="center_vertical"
+ android:orientation="vertical"
+ android:text="Name (set in-code)"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+ </RelativeLayout>
+
+ <fragment
+ android:id="@+id/api_account_settings_select_key_fragment"
+ android:name="org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ tools:layout="@layout/select_secret_key_layout_fragment" />
+
+ <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ custom:foldedLabel="@string/api_settings_show_advanced"
+ custom:unFoldedLabel="@string/api_settings_hide_advanced"
+ custom:foldedIcon="fa-chevron-right"
+ custom:unFoldedIcon="fa-chevron-down">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/label_encryption_algorithm"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <Spinner
+ android:id="@+id/api_account_settings_encryption_algorithm"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/label_hash_algorithm"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <Spinner
+ android:id="@+id/api_account_settings_hash_algorithm"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/label_message_compression"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <Spinner
+ android:id="@+id/api_account_settings_compression"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/api_settings_package_name"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/api_account_settings_package_name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="com.example"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/api_settings_package_signature"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/api_account_settings_package_signature"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Base64 encoded signature"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ </org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/res/layout/api_app_register_activity.xml b/OpenPGP-Keychain/src/main/res/layout/api_app_register_activity.xml
index aa9d59004..f85f3b8f7 100644
--- a/OpenPGP-Keychain/src/main/res/layout/api_app_register_activity.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/api_app_register_activity.xml
@@ -20,7 +20,7 @@
<fragment
android:id="@+id/api_app_settings_fragment"
- android:name="org.sufficientlysecure.keychain.service.remote.AppSettingsFragment"
+ android:name="org.sufficientlysecure.keychain.remote.ui.AppSettingsFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout="@layout/api_app_settings_fragment" />
diff --git a/OpenPGP-Keychain/src/main/res/layout/api_app_settings_activity.xml b/OpenPGP-Keychain/src/main/res/layout/api_app_settings_activity.xml
index d83c8e87d..d38567497 100644
--- a/OpenPGP-Keychain/src/main/res/layout/api_app_settings_activity.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/api_app_settings_activity.xml
@@ -12,10 +12,24 @@
<fragment
android:id="@+id/api_app_settings_fragment"
- android:name="org.sufficientlysecure.keychain.service.remote.AppSettingsFragment"
+ android:name="org.sufficientlysecure.keychain.remote.ui.AppSettingsFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout="@layout/api_app_settings_fragment" />
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/api_settings_accounts"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <FrameLayout
+ android:id="@+id/api_accounts_list_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp" />
+
</LinearLayout>
</ScrollView>
diff --git a/OpenPGP-Keychain/src/main/res/layout/api_app_settings_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/api_app_settings_fragment.xml
index a7917ad4e..96271d418 100644
--- a/OpenPGP-Keychain/src/main/res/layout/api_app_settings_fragment.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/api_app_settings_fragment.xml
@@ -36,57 +36,17 @@
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
- <fragment
- android:id="@+id/api_app_settings_select_key_fragment"
- android:name="org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- tools:layout="@layout/select_secret_key_layout_fragment" />
-
<org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- custom:foldedLabel="@string/btn_encryption_advanced_settings_show"
- custom:unFoldedLabel="@string/btn_encryption_advanced_settings_hide"
+ custom:foldedLabel="@string/api_settings_show_info"
+ custom:unFoldedLabel="@string/api_settings_hide_info"
custom:foldedIcon="fa-chevron-right"
custom:unFoldedIcon="fa-chevron-down">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/label_encryption_algorithm"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <Spinner
- android:id="@+id/api_app_settings_encryption_algorithm"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/label_hash_algorithm"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <Spinner
- android:id="@+id/api_app_settings_hash_algorithm"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/label_message_compression"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <Spinner
- android:id="@+id/api_app_settings_compression"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/api_settings_package_name"
android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/OpenPGP-Keychain/src/main/res/layout/api_apps_list_content.xml b/OpenPGP-Keychain/src/main/res/layout/api_apps_list_content.xml
index b8606b929..9f9b99045 100644
--- a/OpenPGP-Keychain/src/main/res/layout/api_apps_list_content.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/api_apps_list_content.xml
@@ -8,7 +8,7 @@
<fragment
android:id="@+id/crypto_consumers_list_fragment"
- android:name="org.sufficientlysecure.keychain.service.remote.RegisteredAppsListFragment"
+ android:name="org.sufficientlysecure.keychain.remote.ui.AppsListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/res/layout/key_list_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/key_list_fragment.xml
index 77bd6f4e9..f2430f213 100644
--- a/OpenPGP-Keychain/src/main/res/layout/key_list_fragment.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/key_list_fragment.xml
@@ -11,7 +11,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:visibility="gone"
+ android:visibility="visible"
android:gravity="center">
<ProgressBar
@@ -51,7 +51,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:visibility="gone">
<TextView
android:layout_width="wrap_content"
diff --git a/OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_about.html b/OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_about.html
index 5a8f7bde7..d9150a5e8 100644
--- a/OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_start.html b/OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_start.html
index 3a6443a2f..0e60c17a7 100644
--- a/OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-cs-rCZ/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-de/help_about.html b/OpenPGP-Keychain/src/main/res/raw-de/help_about.html
index 4199f9b5e..676c2bdd2 100644
--- a/OpenPGP-Keychain/src/main/res/raw-de/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-de/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Entwickler APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-de/help_start.html b/OpenPGP-Keychain/src/main/res/raw-de/help_start.html
index a7949dd64..7a652682e 100644
--- a/OpenPGP-Keychain/src/main/res/raw-de/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-de/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Los gehts</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-el/help_about.html b/OpenPGP-Keychain/src/main/res/raw-el/help_about.html
index 5a8f7bde7..d9150a5e8 100644
--- a/OpenPGP-Keychain/src/main/res/raw-el/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-el/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-el/help_start.html b/OpenPGP-Keychain/src/main/res/raw-el/help_start.html
index 3a6443a2f..0e60c17a7 100644
--- a/OpenPGP-Keychain/src/main/res/raw-el/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-el/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-es-rCO/help_about.html b/OpenPGP-Keychain/src/main/res/raw-es-rCO/help_about.html
index 5a8f7bde7..d9150a5e8 100644
--- a/OpenPGP-Keychain/src/main/res/raw-es-rCO/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-es-rCO/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-es-rCO/help_start.html b/OpenPGP-Keychain/src/main/res/raw-es-rCO/help_start.html
index 3a6443a2f..0e60c17a7 100644
--- a/OpenPGP-Keychain/src/main/res/raw-es-rCO/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-es-rCO/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-es/help_about.html b/OpenPGP-Keychain/src/main/res/raw-es/help_about.html
index 64d80ab74..552155d68 100644
--- a/OpenPGP-Keychain/src/main/res/raw-es/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-es/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (Parches cryptográficos)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Desarrolladores de APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-es/help_start.html b/OpenPGP-Keychain/src/main/res/raw-es/help_start.html
index 2907bbc99..895b52469 100644
--- a/OpenPGP-Keychain/src/main/res/raw-es/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-es/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Primeros pasos</h2>
-<p>Primero necesitas un par de claves personales. Crea una a través del menú "Mis claves" o importa un par de claves ya existentes a través de "Importar claves". Después, puedes descargar las claves de tus amigos o intercambiarlas a través de códigos QR o NFC.</p>
+<p>Primero necesitas un par de claves personales. Crea una a través del menú "Contactos" o importa un par de claves ya existentes a través de "Importar claves". Después, puedes descargar las claves de tus amigos o intercambiarlas a través de códigos QR o NFC.</p>
<p>Es recomendable que instales <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> para una mejor selección de archivos y <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> para escanear los códigos QR generados. Pulsando en los enlaces se abrirá Google Play o F-Droid.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-fa-rIR/help_about.html b/OpenPGP-Keychain/src/main/res/raw-fa-rIR/help_about.html
index 5a8f7bde7..d9150a5e8 100644
--- a/OpenPGP-Keychain/src/main/res/raw-fa-rIR/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-fa-rIR/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-fr/help_about.html b/OpenPGP-Keychain/src/main/res/raw-fr/help_about.html
index 93e5a5df7..43094ce9d 100644
--- a/OpenPGP-Keychain/src/main/res/raw-fr/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-fr/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (correctif crypto)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar « kalkin » Gadimov (interface utilisateur)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Les développeurs d'APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-fr/help_start.html b/OpenPGP-Keychain/src/main/res/raw-fr/help_start.html
index 0c1610f0c..962c33d86 100644
--- a/OpenPGP-Keychain/src/main/res/raw-fr/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-fr/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Commencer</h2>
-<p>Vous avez d'abord besoin d'une paire de clefs personelles. Créez-en une avec l'option du menu « Mes clefs » ou importez des paires de clefs existantes avec « Importer des clefs ». Ensuite vous pouvez télécharger les clefs de vos amis, ou les échanger par codes QR ou NFC.</p>
+<p>Vous avez d'abord besoin d'une paire de clefs personelles. Créez-en une avec l'option du menu « Contacts » ou importez des paires de clefs existantes avec « Importer des clefs ». Ensuite vous pouvez télécharger les clefs de vos amis, ou les échanger par codes QR ou NFC.</p>
<p>Il vous est recommendé d'installer le <a href="market://details?id=org.openintents.filemanager">gestionnaire de fichiers OI</a> pour sa fonction améliorée de séléction des fichiers et le <a href="market://details?id=com.google.zxing.client.android">lecteur de codes à barres</a> pour balayer les codes QR générés. Cliquer sur les liens ouvrira Google Play Store ou F-Droid pour l'installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-it-rIT/help_about.html b/OpenPGP-Keychain/src/main/res/raw-it-rIT/help_about.html
index 5e4a53ed6..2d17e1882 100644
--- a/OpenPGP-Keychain/src/main/res/raw-it-rIT/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-it-rIT/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (Patch crittografia)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (Interfaccia Utente)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Sviluppatori APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-it-rIT/help_start.html b/OpenPGP-Keychain/src/main/res/raw-it-rIT/help_start.html
index 4eadd82fc..1a4a7303e 100644
--- a/OpenPGP-Keychain/src/main/res/raw-it-rIT/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-it-rIT/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Per iniziare</h2>
-<p>Per prima cosa hai bisogno di un paio di chiavi personali. Creane una tramite i menu di opzione sotto 'Mie Chiavi' o importane di esistenti attraverso "Importa Chiavi". Dopodiche' puoi scaricare le chiavi dei tuoi amici o scambiarle tramite Codici QR o NFC.</p>
+<p>Per prima cosa hai bisogno di un paio di chiavi personali. Creane una tramite i menu di opzione sotto 'Contatti' o importane di esistenti attraverso "Importa Chiavi". Dopodiche' puoi scaricare le chiavi dei tuoi amici o scambiarle tramite Codici QR o NFC.</p>
<p>Si raccomanda di installare <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> per una migliore selezione dei file e <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> per scansionare i codici QR. I collegamenti verranno aperti in Google Play Store o F-Droid per l'installazione.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-ja/help_about.html b/OpenPGP-Keychain/src/main/res/raw-ja/help_about.html
index 72c7616a3..3f630264c 100644
--- a/OpenPGP-Keychain/src/main/res/raw-ja/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-ja/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (暗号関係パッチ提供)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>APG 1.xの開発者達</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-ja/help_start.html b/OpenPGP-Keychain/src/main/res/raw-ja/help_start.html
index 9764e876a..04ad31352 100644
--- a/OpenPGP-Keychain/src/main/res/raw-ja/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-ja/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>入門</h2>
-<p>最初にあなたの個人用鍵ペアが必要になります。オプションメニューの"自分の鍵"で生成するか、"鍵のインポート"から既存の鍵ペアをインポートします。その後、あなたの友人の鍵をダウンロード、もしくはQRコードやNFCで交換します。</p>
+<p>最初にあなたの個人用鍵ペアが必要になります。オプションメニューの"連絡先"で生成するか、"鍵のインポート"から既存の鍵ペアをインポートします。その後、あなたの友人の鍵をダウンロード、もしくはQRコードやNFCで交換します。</p>
<p>ファイルの選択を拡張するには<a href="market://details?id=org.openintents.filemanager">OI File Manager</a>、<a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a>を生成したQRコードのスキャンのため、それぞれのインストールを必要とします。 リンクをクリックして、Google Play Store上かF-Droidからインストールしてください。</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_about.html b/OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_about.html
index 5a8f7bde7..d9150a5e8 100644
--- a/OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_start.html b/OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_start.html
index 3a6443a2f..0e60c17a7 100644
--- a/OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-nl-rNL/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-pl/help_about.html b/OpenPGP-Keychain/src/main/res/raw-pl/help_about.html
index c07fc503f..c41859b60 100644
--- a/OpenPGP-Keychain/src/main/res/raw-pl/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-pl/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (łatki crypto)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (Interfejs Użytkownika)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Deweloperzy APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-pl/help_start.html b/OpenPGP-Keychain/src/main/res/raw-pl/help_start.html
index 539388789..d2faa2db9 100644
--- a/OpenPGP-Keychain/src/main/res/raw-pl/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-pl/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Pierwsze kroki</h2>
-<p>Po pierwsze potrzebujesz swoją osobistą parę kluczy. Stwórz ją, korzystając z odpowiedniej opcji w sekcji "Moje klucze" lub też zaimportuj istniejącą parę korzystając z sekcji "Importuj klucze". Następnie możesz pobrać klucze Twoich znajomych lub wymieniać się z nimi za pośrednictwem kodów QR lub technologii NFC.</p>
+<p>Po pierwsze potrzebujesz swoją osobistą parę kluczy. Stwórz ją, korzystając z odpowiedniej opcji w sekcji "Kontakty" lub też zaimportuj istniejącą parę korzystając z sekcji "Importuj klucze". Następnie możesz pobrać klucze Twoich znajomych lub wymieniać się z nimi za pośrednictwem kodów QR lub technologii NFC.</p>
<p>Zalecana jest instalacja menadżera plików <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> w celu zapewnienia wygodniejszego wyboru plików oraz programu <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a>, który jest w stanie skanować wygenerowane kody QR. Kliknięcie na powyższe linki przekieruje Cię do sklepu Google Play / F-Droid.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_about.html b/OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_about.html
index 5a8f7bde7..d9150a5e8 100644
--- a/OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_start.html b/OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_start.html
index 3a6443a2f..0e60c17a7 100644
--- a/OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-pt-rBR/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-ru/help_about.html b/OpenPGP-Keychain/src/main/res/raw-ru/help_about.html
index 8379bf8de..63335110e 100644
--- a/OpenPGP-Keychain/src/main/res/raw-ru/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-ru/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (патчи криптографии)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Разработчики APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-ru/help_start.html b/OpenPGP-Keychain/src/main/res/raw-ru/help_start.html
index 9b2b99e96..bc9dade67 100644
--- a/OpenPGP-Keychain/src/main/res/raw-ru/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-ru/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Приступая</h2>
-<p>Для начала вам понадобится своя пара ключей. Воспользуйтесь меню в разделе "Мои ключи", что бы создать новую, или добавьте ранее созданную пару в разделе "Импорт ключей". После этого вы сможете скачать ключи ваших друзей или обменяться ключами посредством QR кодов или NFC.</p>
+<p>Для начала вам понадобится своя пара ключей. Воспользуйтесь меню в разделе "Контакты", что бы создать новую, или добавьте ранее созданную пару в разделе "Импорт ключей". После этого вы сможете скачать ключи ваших друзей или обменяться ключами посредством QR кодов или NFC.</p>
<p>Рекомендуется установить <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> для удобного выбора файлов и <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> для распознавания QR кодов. Перейдите по ссылкам на соответствующие страницы Google Play или F-Droid для дальнейшей установки.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_about.html b/OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_about.html
index 5a8f7bde7..d9150a5e8 100644
--- a/OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_start.html b/OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_start.html
index 3a6443a2f..0e60c17a7 100644
--- a/OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-sl-rSI/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-tr/help_about.html b/OpenPGP-Keychain/src/main/res/raw-tr/help_about.html
index 454d16151..d50154765 100644
--- a/OpenPGP-Keychain/src/main/res/raw-tr/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-tr/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (kripto yamaları)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (Arayüz)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Geliştiriciler APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-tr/help_start.html b/OpenPGP-Keychain/src/main/res/raw-tr/help_start.html
index 3a6443a2f..0e60c17a7 100644
--- a/OpenPGP-Keychain/src/main/res/raw-tr/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-tr/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-uk/help_about.html b/OpenPGP-Keychain/src/main/res/raw-uk/help_about.html
index 9526dc0c6..4e6bb02dd 100644
--- a/OpenPGP-Keychain/src/main/res/raw-uk/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-uk/help_about.html
@@ -11,6 +11,12 @@
<li>Аш Гюдж (латки шифрування)</li>
<li>Браян С. Барнс</li>
<li>Бахтіяр 'kalkin' Ґадімов (інтерфейс)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Розробники APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-uk/help_start.html b/OpenPGP-Keychain/src/main/res/raw-uk/help_start.html
index 3bfb40f8a..78443070d 100644
--- a/OpenPGP-Keychain/src/main/res/raw-uk/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-uk/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Приступаючи до роботи</h2>
-<p>Спершу вам потрібна персональна в'язка ключів. Створіть одну через меню параметрів у "Мої Ключі" або імпортуйте наявні в'язки ключів через "Імпорт ключів". Після цього ви зможете завантажувати ключі ваших друзів чи обміняти їх через штрих-коди або NFC.</p>
+<p>Спершу вам потрібна персональна в'язка ключів. Створіть одну через меню параметрів у "Контакти" або імпортуйте наявні в'язки ключів через "Імпорт ключів". Після цього ви зможете завантажувати ключі ваших друзів чи обміняти їх через штрих-коди або NFC.</p>
<p>Рекомендуємо вам встановити <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> для поліпшеного виділення файлів та <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> для сканування згенерованих штрих-кодів. Натискання посилань відкриє Google Play або F-Droid для встановлення.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_about.html b/OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_about.html
index 5a8f7bde7..d9150a5e8 100644
--- a/OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_start.html b/OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_start.html
index 3a6443a2f..0e60c17a7 100644
--- a/OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw-zh-rTW/help_start.html
@@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/raw-zh/help_about.html b/OpenPGP-Keychain/src/main/res/raw-zh/help_about.html
index 6d00fc6a1..1eec8bdbf 100644
--- a/OpenPGP-Keychain/src/main/res/raw-zh/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw-zh/help_about.html
@@ -11,6 +11,12 @@
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (介面)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw/help_about.html b/OpenPGP-Keychain/src/main/res/raw/help_about.html
index 8d7714365..2ffbb47a6 100644
--- a/OpenPGP-Keychain/src/main/res/raw/help_about.html
+++ b/OpenPGP-Keychain/src/main/res/raw/help_about.html
@@ -15,6 +15,12 @@ And don't add newlines before or after p tags because of transifex -->
<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+<li>Daniel Hammann</li>
+<li>Daniel Haß</li>
+<li>Greg Witczak</li>
+<li>Miroojin Bakshi</li>
+<li>Paul Sarbinowski</li>
+<li>Vincent Breitmoser</li>
</ul>
<h2>Developers APG 1.x</h2>
diff --git a/OpenPGP-Keychain/src/main/res/raw/help_start.html b/OpenPGP-Keychain/src/main/res/raw/help_start.html
index 7afac0f08..56c02b1fd 100644
--- a/OpenPGP-Keychain/src/main/res/raw/help_start.html
+++ b/OpenPGP-Keychain/src/main/res/raw/help_start.html
@@ -6,7 +6,7 @@ And don't add newlines before or after p tags because of transifex -->
</head>
<body>
<h2>Getting started</h2>
-<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
+<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
diff --git a/OpenPGP-Keychain/src/main/res/values/strings.xml b/OpenPGP-Keychain/src/main/res/values/strings.xml
index 11e3028f3..5bf7ca8ca 100644
--- a/OpenPGP-Keychain/src/main/res/values/strings.xml
+++ b/OpenPGP-Keychain/src/main/res/values/strings.xml
@@ -412,6 +412,8 @@
<!-- Remote API -->
<string name="api_no_apps">No registered applications!\n\nThird-party applications can request access to OpenKeychain. After granting access, they will be listed here.</string>
+ <string name="api_settings_show_info">Show advanced information</string>
+ <string name="api_settings_hide_info">Hide advanced information</string>
<string name="api_settings_show_advanced">Show advanced settings</string>
<string name="api_settings_hide_advanced">Hide advanced settings</string>
<string name="api_settings_no_key">No key selected</string>
@@ -421,6 +423,8 @@
<string name="api_settings_revoke">Revoke access</string>
<string name="api_settings_package_name">Package Name</string>
<string name="api_settings_package_signature">SHA-256 of Package Signature</string>
+ <string name="api_settings_accounts">Accounts</string>
+ <string name="api_settings_accounts_empty">No accounts attached to this application.</string>
<string name="api_register_text">The displayed application requests access to OpenKeychain.\nAllow access?\n\nWARNING: If you do not know why this screen appeared, disallow access! You can revoke access later using the \'Registered Applications\' screen.</string>
<string name="api_register_allow">Allow access</string>
<string name="api_register_disallow">Disallow access</string>