aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--OpenPGP-Keychain-API-Demo/AndroidManifest.xml4
-rw-r--r--OpenPGP-Keychain-API-Demo/project.properties2
-rw-r--r--OpenPGP-Keychain-API-Demo/res/xml/base_preference.xml3
-rw-r--r--OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/IOpenPgpService.aidl28
-rw-r--r--OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpConstants.java10
-rw-r--r--OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpHelper.java2
-rw-r--r--OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpListPreference.java40
-rw-r--r--OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpServiceConnection.java32
-rw-r--r--OpenPGP-Keychain/AndroidManifest.xml3
-rw-r--r--OpenPGP-Keychain/build.gradle9
-rw-r--r--OpenPGP-Keychain/project.properties3
-rw-r--r--OpenPGP-Keychain/res/drawable-xhdpi/icon.pngbin8165 -> 8165 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-xxhdpi/icon.pngbin0 -> 14633 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-xxxhdpi/icon.pngbin0 -> 21592 bytes
-rw-r--r--OpenPGP-Keychain/res/layout/api_app_error_message.xml17
-rw-r--r--OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml219
-rw-r--r--OpenPGP-Keychain/res/values/strings.xml5
-rw-r--r--OpenPGP-Keychain/src/org/openintents/openpgp/IOpenPgpService.aidl1
-rw-r--r--OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpConstants.java10
-rw-r--r--OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpHelper.java2
-rw-r--r--OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpListPreference.java38
-rw-r--r--OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpServiceConnection.java32
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ActionBarHelper.java13
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java1
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java13
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java25
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java10
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java12
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java23
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java152
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java29
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java38
-rw-r--r--README.md33
-rw-r--r--Resources/Graphics/icon_googlecode.pngbin3643 -> 0 bytes
-rw-r--r--Resources/graphics/dashboard_decrypt_default.svg (renamed from Resources/Graphics/dashboard_decrypt_default.svg)0
-rw-r--r--Resources/graphics/dashboard_decrypt_pressed.svg (renamed from Resources/Graphics/dashboard_decrypt_pressed.svg)0
-rw-r--r--Resources/graphics/dashboard_encrypt_default.svg (renamed from Resources/Graphics/dashboard_encrypt_default.svg)0
-rw-r--r--Resources/graphics/dashboard_encrypt_pressed.svg (renamed from Resources/Graphics/dashboard_encrypt_pressed.svg)0
-rwxr-xr-xResources/graphics/dashboard_help_default.svg (renamed from Resources/Graphics/dashboard_help_default.svg)0
-rw-r--r--Resources/graphics/dashboard_help_pressed.svg (renamed from Resources/Graphics/dashboard_help_pressed.svg)0
-rw-r--r--Resources/graphics/dashboard_import_default.svg (renamed from Resources/Graphics/dashboard_import_default.svg)0
-rw-r--r--Resources/graphics/dashboard_import_pressed.svg (renamed from Resources/Graphics/dashboard_import_pressed.svg)0
-rw-r--r--Resources/graphics/dashboard_manage_keys_default.svg (renamed from Resources/Graphics/dashboard_manage_keys_default.svg)0
-rw-r--r--Resources/graphics/dashboard_manage_keys_pressed.svg (renamed from Resources/Graphics/dashboard_manage_keys_pressed.svg)0
-rw-r--r--Resources/graphics/dashboard_my_keys_default.svg (renamed from Resources/Graphics/dashboard_my_keys_default.svg)0
-rw-r--r--Resources/graphics/dashboard_my_keys_pressed.svg (renamed from Resources/Graphics/dashboard_my_keys_pressed.svg)0
-rw-r--r--Resources/graphics/dashboard_scan_qrcode_default.svg (renamed from Resources/Graphics/dashboard_scan_qrcode_default.svg)0
-rw-r--r--Resources/graphics/dashboard_scan_qrcode_pressed.svg (renamed from Resources/Graphics/dashboard_scan_qrcode_pressed.svg)0
-rw-r--r--Resources/graphics/icon.png (renamed from Resources/Graphics/icon_google_play.png)bin81207 -> 81207 bytes
-rw-r--r--Resources/graphics/icon.svg (renamed from Resources/Graphics/icon.svg)0
-rw-r--r--Resources/graphics/icon_sizes.txt (renamed from Resources/Graphics/icon_sizes.txt)0
-rw-r--r--Resources/graphics/key.svg (renamed from Resources/Graphics/key.svg)0
-rw-r--r--Resources/graphics/kgpg_key2_kopete.svgz (renamed from Resources/Graphics/kgpg_key2_kopete.svgz)bin36830 -> 36830 bytes
-rwxr-xr-xResources/graphics/update-icon.sh32
-rw-r--r--Resources/screenshots/screenshot1.png (renamed from Resources/Screenshots/screenshot1.png)bin35361 -> 35361 bytes
-rw-r--r--Resources/screenshots/screenshot2.png (renamed from Resources/Screenshots/screenshot2.png)bin27660 -> 27660 bytes
-rw-r--r--Resources/screenshots/screenshot3.png (renamed from Resources/Screenshots/screenshot3.png)bin26405 -> 26405 bytes
-rw-r--r--Resources/screenshots/screenshot4.png (renamed from Resources/Screenshots/screenshot4.png)bin30530 -> 30530 bytes
-rw-r--r--Resources/screenshots/screenshot5.png (renamed from Resources/Screenshots/screenshot5.png)bin22315 -> 22315 bytes
-rw-r--r--build.gradle4
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin0 -> 50514 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xgradlew164
-rw-r--r--gradlew.bat90
-rw-r--r--libraries/HtmlTextView/build.gradle2
-rw-r--r--settings.gradle3
68 files changed, 799 insertions, 316 deletions
diff --git a/.gitignore b/.gitignore
index afa9dfc45..71c11b159 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,9 +14,6 @@ ant.properties
.gradle
build
gradle.properties
-gradlew
-gradlew.bat
-gradle
#Maven
target
diff --git a/OpenPGP-Keychain-API-Demo/AndroidManifest.xml b/OpenPGP-Keychain-API-Demo/AndroidManifest.xml
index 2543f0129..8b8c43776 100644
--- a/OpenPGP-Keychain-API-Demo/AndroidManifest.xml
+++ b/OpenPGP-Keychain-API-Demo/AndroidManifest.xml
@@ -5,8 +5,8 @@
android:versionName="1.1" >
<uses-sdk
- android:minSdkVersion="7"
- android:targetSdkVersion="18" />
+ android:minSdkVersion="8"
+ android:targetSdkVersion="19" />
<application
android:allowBackup="true"
diff --git a/OpenPGP-Keychain-API-Demo/project.properties b/OpenPGP-Keychain-API-Demo/project.properties
index 73fc66102..a5578ba09 100644
--- a/OpenPGP-Keychain-API-Demo/project.properties
+++ b/OpenPGP-Keychain-API-Demo/project.properties
@@ -8,4 +8,4 @@
# project structure.
# Project target.
-target=android-18
+target=android-19
diff --git a/OpenPGP-Keychain-API-Demo/res/xml/base_preference.xml b/OpenPGP-Keychain-API-Demo/res/xml/base_preference.xml
index f36c5f5a9..5febfad44 100644
--- a/OpenPGP-Keychain-API-Demo/res/xml/base_preference.xml
+++ b/OpenPGP-Keychain-API-Demo/res/xml/base_preference.xml
@@ -12,6 +12,9 @@
<!-- android:title="AIDL Demo (ACCESS_KEYS permission)" /> -->
<!-- </PreferenceCategory> -->
<PreferenceCategory android:title="OpenPGP Provider" >
+ <org.openintents.openpgp.OpenPgpListPreference
+ android:key="openpgp_provider_list"
+ android:title="Select OpenPGP Provider!" />
<Preference
android:key="openpgp_provider_demo"
android:title="OpenPGP Provider" />
diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/IOpenPgpService.aidl b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/IOpenPgpService.aidl
index 69a608dc6..8f9e8a0fd 100644
--- a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/IOpenPgpService.aidl
+++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/IOpenPgpService.aidl
@@ -25,12 +25,12 @@ import org.openintents.openpgp.IOpenPgpKeyIdsCallback;
* Results are returned to the callback, which has to be implemented on client side.
*/
interface IOpenPgpService {
-
+
/**
- * Encrypt
- *
- * After successful encryption, callback's onSuccess will contain the resulting output bytes.
+ * Sign
*
+ * After successful signing, callback's onSuccess will contain the resulting output.
+ *
* @param input
* OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri
* @param output
@@ -45,18 +45,16 @@ interface IOpenPgpService {
* Writes output to given Uri
* new OpenPgpData(fileDescriptor)
* Writes output to given ParcelFileDescriptor
- * @param keyIds
- * Key Ids of recipients. Can be retrieved with getKeyIds()
* @param callback
* Callback where to return results
*/
- oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback);
+ oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback);
/**
- * Sign
+ * Encrypt
+ *
+ * After successful encryption, callback's onSuccess will contain the resulting output.
*
- * After successful signing, callback's onSuccess will contain the resulting output bytes.
- *
* @param input
* OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri
* @param output
@@ -71,15 +69,17 @@ interface IOpenPgpService {
* Writes output to given Uri
* new OpenPgpData(fileDescriptor)
* Writes output to given ParcelFileDescriptor
+ * @param keyIds
+ * Key Ids of recipients. Can be retrieved with getKeyIds()
* @param callback
* Callback where to return results
*/
- oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback);
+ oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback);
/**
* Sign then encrypt
*
- * After successful signing and encryption, callback's onSuccess will contain the resulting output bytes.
+ * After successful signing and encryption, callback's onSuccess will contain the resulting output.
*
* @param input
* OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri
@@ -104,9 +104,9 @@ interface IOpenPgpService {
/**
* Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted,
- * and also signed-only inputBytes.
+ * and also signed-only input.
*
- * After successful decryption/verification, callback's onSuccess will contain the resulting output bytes.
+ * After successful decryption/verification, callback's onSuccess will contain the resulting output.
* The signatureResult in onSuccess is only non-null if signed-and-encrypted or signed-only inputBytes were given.
*
* @param input
diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpConstants.java b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpConstants.java
new file mode 100644
index 000000000..b1ca1bfe6
--- /dev/null
+++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpConstants.java
@@ -0,0 +1,10 @@
+package org.openintents.openpgp;
+
+public class OpenPgpConstants {
+
+ public static final String TAG = "OpenPgp API";
+
+ public static final int REQUIRED_API_VERSION = 1;
+ public static final String SERVICE_INTENT = "org.openintents.openpgp.IOpenPgpService";
+
+}
diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpHelper.java b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpHelper.java
index 56c4a4dca..7305c47ce 100644
--- a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpHelper.java
+++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpHelper.java
@@ -40,7 +40,7 @@ public class OpenPgpHelper {
}
public boolean isAvailable() {
- Intent intent = new Intent(IOpenPgpService.class.getName());
+ Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT);
List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(intent, 0);
if (!resInfo.isEmpty()) {
return true;
diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpListPreference.java b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpListPreference.java
index 551401b18..c8e709df9 100644
--- a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpListPreference.java
+++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpListPreference.java
@@ -26,6 +26,8 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.preference.DialogPreference;
import android.util.AttributeSet;
@@ -39,22 +41,19 @@ public class OpenPgpListPreference extends DialogPreference {
ArrayList<OpenPgpProviderEntry> mProviderList = new ArrayList<OpenPgpProviderEntry>();
private String mSelectedPackage;
- public static final int REQUIRED_API_VERSION = 1;
-
public OpenPgpListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
- List<ResolveInfo> resInfo =
- context.getPackageManager().queryIntentServices(
- new Intent(IOpenPgpService.class.getName()), PackageManager.GET_META_DATA);
+ List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(
+ new Intent(OpenPgpConstants.SERVICE_INTENT), PackageManager.GET_META_DATA);
if (!resInfo.isEmpty()) {
for (ResolveInfo resolveInfo : resInfo) {
if (resolveInfo.serviceInfo == null)
continue;
String packageName = resolveInfo.serviceInfo.packageName;
- String simpleName = String.valueOf(resolveInfo.serviceInfo
- .loadLabel(context.getPackageManager()));
+ String simpleName = String.valueOf(resolveInfo.serviceInfo.loadLabel(context
+ .getPackageManager()));
Drawable icon = resolveInfo.serviceInfo.loadIcon(context.getPackageManager());
// get api version
@@ -95,22 +94,20 @@ public class OpenPgpListPreference extends DialogPreference {
TextView tv = (TextView) v.findViewById(android.R.id.text1);
// Put the image on the TextView
- tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon,
- null, null, null);
+ tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon, null,
+ null, null);
- // Add margin between image and text (support various screen
- // densities)
- int dp5 = (int) (5 * getContext().getResources().getDisplayMetrics().density + 0.5f);
- tv.setCompoundDrawablePadding(dp5);
+ // Add margin between image and text (support various screen densities)
+ int dp10 = (int) (10 * getContext().getResources().getDisplayMetrics().density + 0.5f);
+ tv.setCompoundDrawablePadding(dp10);
// disable if it has the wrong api_version
- if (mProviderList.get(position).apiVersion == REQUIRED_API_VERSION) {
+ if (mProviderList.get(position).apiVersion == OpenPgpConstants.REQUIRED_API_VERSION) {
tv.setEnabled(true);
} else {
tv.setEnabled(false);
- tv.setText(tv.getText() + " (API v"
- + mProviderList.get(position).apiVersion + ", needs v"
- + REQUIRED_API_VERSION + ")");
+ tv.setText(tv.getText() + " (API v" + mProviderList.get(position).apiVersion
+ + ", needs v" + OpenPgpConstants.REQUIRED_API_VERSION + ")");
}
return v;
@@ -125,8 +122,8 @@ public class OpenPgpListPreference extends DialogPreference {
mSelectedPackage = mProviderList.get(which).packageName;
/*
- * Clicking on an item simulates the positive button
- * click, and dismisses the dialog.
+ * Clicking on an item simulates the positive button click, and dismisses
+ * the dialog.
*/
OpenPgpListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
dialog.dismiss();
@@ -134,9 +131,8 @@ public class OpenPgpListPreference extends DialogPreference {
});
/*
- * The typical interaction for list-based dialogs is to have
- * click-on-an-item dismiss the dialog instead of the user having to
- * press 'Ok'.
+ * The typical interaction for list-based dialogs is to have click-on-an-item dismiss the
+ * dialog instead of the user having to press 'Ok'.
*/
builder.setPositiveButton(null, null);
}
diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpServiceConnection.java b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpServiceConnection.java
index 56a922d73..f7ba06aaf 100644
--- a/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpServiceConnection.java
+++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpServiceConnection.java
@@ -29,14 +29,12 @@ public class OpenPgpServiceConnection {
private Context mApplicationContext;
private IOpenPgpService mService;
- private boolean bound;
- private String cryptoProviderPackageName;
-
- private static final String TAG = "OpenPgpServiceConnection";
+ private boolean mBound;
+ private String mCryptoProviderPackageName;
public OpenPgpServiceConnection(Context context, String cryptoProviderPackageName) {
- mApplicationContext = context.getApplicationContext();
- this.cryptoProviderPackageName = cryptoProviderPackageName;
+ this.mApplicationContext = context.getApplicationContext();
+ this.mCryptoProviderPackageName = cryptoProviderPackageName;
}
public IOpenPgpService getService() {
@@ -44,20 +42,20 @@ public class OpenPgpServiceConnection {
}
public boolean isBound() {
- return bound;
+ return mBound;
}
private ServiceConnection mCryptoServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IOpenPgpService.Stub.asInterface(service);
- Log.d(TAG, "connected to service");
- bound = true;
+ Log.d(OpenPgpConstants.TAG, "connected to service");
+ mBound = true;
}
public void onServiceDisconnected(ComponentName name) {
mService = null;
- Log.d(TAG, "disconnected from service");
- bound = false;
+ Log.d(OpenPgpConstants.TAG, "disconnected from service");
+ mBound = false;
}
};
@@ -67,23 +65,23 @@ public class OpenPgpServiceConnection {
* @return
*/
public boolean bindToService() {
- if (mService == null && !bound) { // if not already connected
+ if (mService == null && !mBound) { // if not already connected
try {
- Log.d(TAG, "not bound yet");
+ Log.d(OpenPgpConstants.TAG, "not bound yet");
Intent serviceIntent = new Intent();
serviceIntent.setAction(IOpenPgpService.class.getName());
- serviceIntent.setPackage(cryptoProviderPackageName);
+ serviceIntent.setPackage(mCryptoProviderPackageName);
mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection,
Context.BIND_AUTO_CREATE);
return true;
} catch (Exception e) {
- Log.d(TAG, "Exception", e);
+ Log.d(OpenPgpConstants.TAG, "Exception on binding", e);
return false;
}
- } else { // already connected
- Log.d(TAG, "already bound... ");
+ } else {
+ Log.d(OpenPgpConstants.TAG, "already bound");
return true;
}
}
diff --git a/OpenPGP-Keychain/AndroidManifest.xml b/OpenPGP-Keychain/AndroidManifest.xml
index e363047e6..4b843bc01 100644
--- a/OpenPGP-Keychain/AndroidManifest.xml
+++ b/OpenPGP-Keychain/AndroidManifest.xml
@@ -47,7 +47,7 @@
<uses-sdk
android:minSdkVersion="8"
- android:targetSdkVersion="18" />
+ android:targetSdkVersion="19" />
<uses-feature
android:name="android.hardware.wifi"
@@ -65,7 +65,6 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.NFC" />
- <uses-permission android:name="com.fsck.k9.permission.READ_ATTACHMENT" />
<!-- android:allowBackup="false": Don't allow backup over adb backup or other apps! -->
<application
diff --git a/OpenPGP-Keychain/build.gradle b/OpenPGP-Keychain/build.gradle
index 5d55d1ea5..80c0f05cd 100644
--- a/OpenPGP-Keychain/build.gradle
+++ b/OpenPGP-Keychain/build.gradle
@@ -4,7 +4,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.5.+'
+ classpath 'com.android.tools.build:gradle:0.6.3'
}
}
@@ -22,15 +22,16 @@ dependencies {
compile 'com.android.support:support-v4:18.0.+' // already in actionbarsherlock
compile project(':libraries:ActionBarSherlock')
compile project(':libraries:HtmlTextView')
+ compile project(':libraries:pinned-section-listview:library')
}
android {
- compileSdkVersion 18
- buildToolsVersion "18.0.1"
+ compileSdkVersion 19
+ buildToolsVersion "19"
defaultConfig {
minSdkVersion 8
- targetSdkVersion 18
+ targetSdkVersion 19
}
sourceSets {
diff --git a/OpenPGP-Keychain/project.properties b/OpenPGP-Keychain/project.properties
index 084aff4b6..7347abfcd 100644
--- a/OpenPGP-Keychain/project.properties
+++ b/OpenPGP-Keychain/project.properties
@@ -8,6 +8,7 @@
# project structure.
# Project target.
-target=android-18
+target=android-19
android.library.reference.1=../libraries/ActionBarSherlock
android.library.reference.2=../libraries/HtmlTextView
+android.library.reference.3=../libraries/pinned-section-listview/library
diff --git a/OpenPGP-Keychain/res/drawable-xhdpi/icon.png b/OpenPGP-Keychain/res/drawable-xhdpi/icon.png
index 03ee31bbd..ec8e9fc6d 100644
--- a/OpenPGP-Keychain/res/drawable-xhdpi/icon.png
+++ b/OpenPGP-Keychain/res/drawable-xhdpi/icon.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-xxhdpi/icon.png b/OpenPGP-Keychain/res/drawable-xxhdpi/icon.png
new file mode 100644
index 000000000..a55413501
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-xxhdpi/icon.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-xxxhdpi/icon.png b/OpenPGP-Keychain/res/drawable-xxxhdpi/icon.png
new file mode 100644
index 000000000..d4c77573e
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-xxxhdpi/icon.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/layout/api_app_error_message.xml b/OpenPGP-Keychain/res/layout/api_app_error_message.xml
new file mode 100644
index 000000000..5927dbf43
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/api_app_error_message.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <org.sufficientlysecure.htmltextview.HtmlTextView
+ android:id="@+id/api_app_error_message_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:paddingBottom="0dip"
+ android:text="Set in-code!"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml b/OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml
index 81b48be72..a40444e0f 100644
--- a/OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml
+++ b/OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml
@@ -1,122 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
- <RelativeLayout
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:gravity="center_horizontal"
- android:orientation="horizontal"
- android:paddingBottom="3dip" >
-
- <ImageView
- android:id="@+id/api_app_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_app_settings_app_name"
- android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:gravity="center_horizontal"
+ android:orientation="horizontal"
+ android:paddingBottom="3dip" >
+
+ <ImageView
+ android:id="@+id/api_app_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_app_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>
+
+ <LinearLayout
+ android:layout_width="match_parent"
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>
+ android:orientation="horizontal" >
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
+ <Button
+ android:id="@+id/api_app_settings_select_key_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/api_settings_select_key" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="16dp" >
+
+ <TextView
+ android:id="@+id/api_app_settings_user_id"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:text="@string/api_settings_no_key"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/api_app_settings_user_id_rest"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:text=""
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
+ </LinearLayout>
<Button
- android:id="@+id/api_app_settings_select_key_button"
- android:layout_width="wrap_content"
+ android:id="@+id/api_app_settings_advanced_button"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/api_settings_select_key" />
+ android:text="@string/api_settings_show_advanced" />
<LinearLayout
- android:layout_width="fill_parent"
+ android:id="@+id/api_app_settings_advanced"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingLeft="16dp" >
+ android:visibility="gone" >
<TextView
- android:id="@+id/api_app_settings_user_id"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:ellipsize="end"
- android:singleLine="true"
- android:text="@string/api_settings_no_key"
+ 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:id="@+id/api_app_settings_user_id_rest"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:ellipsize="end"
- android:singleLine="true"
- android:text=""
- android:textAppearance="?android:attr/textAppearanceSmall" />
- </LinearLayout>
- </LinearLayout>
-
- <Button
- android:id="@+id/api_app_settings_advanced_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/api_settings_show_advanced" />
+ android:text="@string/label_hash_algorithm"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
- <LinearLayout
- android:id="@+id/api_app_settings_advanced"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="invisible" >
+ <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_encryption_algorithm"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ <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_encryption_algorithm"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ <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/label_hash_algorithm"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/api_settings_package_name"
+ 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:id="@+id/api_app_settings_package_name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="com.example"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/label_message_compression"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/api_settings_package_signature"
+ 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:id="@+id/api_app_settings_package_signature"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Base64 encoded signature"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
</LinearLayout>
-</LinearLayout> \ No newline at end of file
+</ScrollView> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/values/strings.xml b/OpenPGP-Keychain/res/values/strings.xml
index 02e1e5bd1..c3736815c 100644
--- a/OpenPGP-Keychain/res/values/strings.xml
+++ b/OpenPGP-Keychain/res/values/strings.xml
@@ -317,7 +317,7 @@
<string name="import_qr_code_missing">Missing QR Codes: %1$s</string>
<string name="import_qr_code_wrong">QR Code malformed! Please try again!</string>
<string name="import_qr_code_finished">QR Code scanning finished!</string>
-
+
<!-- Intent labels -->
<string name="intent_decrypt_file">OpenPGP: Decrypt File</string>
<string name="intent_import_key">OpenPGP: Import Key</string>
@@ -333,6 +333,8 @@
<string name="api_settings_save">Save</string>
<string name="api_settings_cancel">Cancel</string>
<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_register_text">The following application requests access to OpenPGP Keychain\'s API.\n\nAllow permanent access?</string>
<string name="api_register_allow">Allow access</string>
<string name="api_register_disallow">Disallow access</string>
@@ -340,6 +342,7 @@
<string name="api_select_pub_keys_missing_text">No public keys were found for these user ids:</string>
<string name="api_select_pub_keys_dublicates_text">More than one public key exist for these user ids:</string>
<string name="api_select_pub_keys_text">Please review the list of recipients!</string>
+ <string name="api_error_wrong_signature">Signature check failed! Have you installed this app from a different source? If you are sure that this is not an attack, revoke this app\'s registration in OpenPGP Keychain and then register the app again.</string>
<!-- Share -->
<string name="share_qr_code_dialog_start">Go through all QR Codes using \'Next\', and scan them one by one.</string>
diff --git a/OpenPGP-Keychain/src/org/openintents/openpgp/IOpenPgpService.aidl b/OpenPGP-Keychain/src/org/openintents/openpgp/IOpenPgpService.aidl
index 7cbf96b56..8f9e8a0fd 100644
--- a/OpenPGP-Keychain/src/org/openintents/openpgp/IOpenPgpService.aidl
+++ b/OpenPGP-Keychain/src/org/openintents/openpgp/IOpenPgpService.aidl
@@ -50,7 +50,6 @@ interface IOpenPgpService {
*/
oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback);
-
/**
* Encrypt
*
diff --git a/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpConstants.java b/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpConstants.java
new file mode 100644
index 000000000..b1ca1bfe6
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpConstants.java
@@ -0,0 +1,10 @@
+package org.openintents.openpgp;
+
+public class OpenPgpConstants {
+
+ public static final String TAG = "OpenPgp API";
+
+ public static final int REQUIRED_API_VERSION = 1;
+ public static final String SERVICE_INTENT = "org.openintents.openpgp.IOpenPgpService";
+
+}
diff --git a/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpHelper.java b/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpHelper.java
index 56c4a4dca..7305c47ce 100644
--- a/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpHelper.java
+++ b/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpHelper.java
@@ -40,7 +40,7 @@ public class OpenPgpHelper {
}
public boolean isAvailable() {
- Intent intent = new Intent(IOpenPgpService.class.getName());
+ Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT);
List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(intent, 0);
if (!resInfo.isEmpty()) {
return true;
diff --git a/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpListPreference.java b/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpListPreference.java
index 551401b18..4ddd97485 100644
--- a/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpListPreference.java
+++ b/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpListPreference.java
@@ -39,22 +39,19 @@ public class OpenPgpListPreference extends DialogPreference {
ArrayList<OpenPgpProviderEntry> mProviderList = new ArrayList<OpenPgpProviderEntry>();
private String mSelectedPackage;
- public static final int REQUIRED_API_VERSION = 1;
-
public OpenPgpListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
- List<ResolveInfo> resInfo =
- context.getPackageManager().queryIntentServices(
- new Intent(IOpenPgpService.class.getName()), PackageManager.GET_META_DATA);
+ List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(
+ new Intent(OpenPgpConstants.SERVICE_INTENT), PackageManager.GET_META_DATA);
if (!resInfo.isEmpty()) {
for (ResolveInfo resolveInfo : resInfo) {
if (resolveInfo.serviceInfo == null)
continue;
String packageName = resolveInfo.serviceInfo.packageName;
- String simpleName = String.valueOf(resolveInfo.serviceInfo
- .loadLabel(context.getPackageManager()));
+ String simpleName = String.valueOf(resolveInfo.serviceInfo.loadLabel(context
+ .getPackageManager()));
Drawable icon = resolveInfo.serviceInfo.loadIcon(context.getPackageManager());
// get api version
@@ -95,22 +92,20 @@ public class OpenPgpListPreference extends DialogPreference {
TextView tv = (TextView) v.findViewById(android.R.id.text1);
// Put the image on the TextView
- tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon,
- null, null, null);
+ tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon, null,
+ null, null);
- // Add margin between image and text (support various screen
- // densities)
- int dp5 = (int) (5 * getContext().getResources().getDisplayMetrics().density + 0.5f);
- tv.setCompoundDrawablePadding(dp5);
+ // Add margin between image and text (support various screen densities)
+ int dp10 = (int) (10 * getContext().getResources().getDisplayMetrics().density + 0.5f);
+ tv.setCompoundDrawablePadding(dp10);
// disable if it has the wrong api_version
- if (mProviderList.get(position).apiVersion == REQUIRED_API_VERSION) {
+ if (mProviderList.get(position).apiVersion == OpenPgpConstants.REQUIRED_API_VERSION) {
tv.setEnabled(true);
} else {
tv.setEnabled(false);
- tv.setText(tv.getText() + " (API v"
- + mProviderList.get(position).apiVersion + ", needs v"
- + REQUIRED_API_VERSION + ")");
+ tv.setText(tv.getText() + " (API v" + mProviderList.get(position).apiVersion
+ + ", needs v" + OpenPgpConstants.REQUIRED_API_VERSION + ")");
}
return v;
@@ -125,8 +120,8 @@ public class OpenPgpListPreference extends DialogPreference {
mSelectedPackage = mProviderList.get(which).packageName;
/*
- * Clicking on an item simulates the positive button
- * click, and dismisses the dialog.
+ * Clicking on an item simulates the positive button click, and dismisses
+ * the dialog.
*/
OpenPgpListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
dialog.dismiss();
@@ -134,9 +129,8 @@ public class OpenPgpListPreference extends DialogPreference {
});
/*
- * The typical interaction for list-based dialogs is to have
- * click-on-an-item dismiss the dialog instead of the user having to
- * press 'Ok'.
+ * The typical interaction for list-based dialogs is to have click-on-an-item dismiss the
+ * dialog instead of the user having to press 'Ok'.
*/
builder.setPositiveButton(null, null);
}
diff --git a/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpServiceConnection.java b/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpServiceConnection.java
index 56a922d73..f7ba06aaf 100644
--- a/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpServiceConnection.java
+++ b/OpenPGP-Keychain/src/org/openintents/openpgp/OpenPgpServiceConnection.java
@@ -29,14 +29,12 @@ public class OpenPgpServiceConnection {
private Context mApplicationContext;
private IOpenPgpService mService;
- private boolean bound;
- private String cryptoProviderPackageName;
-
- private static final String TAG = "OpenPgpServiceConnection";
+ private boolean mBound;
+ private String mCryptoProviderPackageName;
public OpenPgpServiceConnection(Context context, String cryptoProviderPackageName) {
- mApplicationContext = context.getApplicationContext();
- this.cryptoProviderPackageName = cryptoProviderPackageName;
+ this.mApplicationContext = context.getApplicationContext();
+ this.mCryptoProviderPackageName = cryptoProviderPackageName;
}
public IOpenPgpService getService() {
@@ -44,20 +42,20 @@ public class OpenPgpServiceConnection {
}
public boolean isBound() {
- return bound;
+ return mBound;
}
private ServiceConnection mCryptoServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IOpenPgpService.Stub.asInterface(service);
- Log.d(TAG, "connected to service");
- bound = true;
+ Log.d(OpenPgpConstants.TAG, "connected to service");
+ mBound = true;
}
public void onServiceDisconnected(ComponentName name) {
mService = null;
- Log.d(TAG, "disconnected from service");
- bound = false;
+ Log.d(OpenPgpConstants.TAG, "disconnected from service");
+ mBound = false;
}
};
@@ -67,23 +65,23 @@ public class OpenPgpServiceConnection {
* @return
*/
public boolean bindToService() {
- if (mService == null && !bound) { // if not already connected
+ if (mService == null && !mBound) { // if not already connected
try {
- Log.d(TAG, "not bound yet");
+ Log.d(OpenPgpConstants.TAG, "not bound yet");
Intent serviceIntent = new Intent();
serviceIntent.setAction(IOpenPgpService.class.getName());
- serviceIntent.setPackage(cryptoProviderPackageName);
+ serviceIntent.setPackage(mCryptoProviderPackageName);
mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection,
Context.BIND_AUTO_CREATE);
return true;
} catch (Exception e) {
- Log.d(TAG, "Exception", e);
+ Log.d(OpenPgpConstants.TAG, "Exception on binding", e);
return false;
}
- } else { // already connected
- Log.d(TAG, "already bound... ");
+ } else {
+ Log.d(OpenPgpConstants.TAG, "already bound");
return true;
}
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ActionBarHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ActionBarHelper.java
index c0fc4df86..fee120273 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ActionBarHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ActionBarHelper.java
@@ -81,8 +81,9 @@ public class ActionBarHelper {
cancelOnClickListener);
// Show the custom action bar view and hide the normal Home icon and title.
- actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM
- | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
+ actionBar.setDisplayShowTitleEnabled(false);
+ actionBar.setDisplayShowHomeEnabled(false);
+ actionBar.setDisplayShowCustomEnabled(true);
actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
@@ -102,14 +103,14 @@ public class ActionBarHelper {
final View customActionBarView = inflater
.inflate(R.layout.actionbar_custom_view_done, null);
- ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text))
- .setText(R.string.api_settings_save);
+ ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)).setText(doneText);
customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
doneOnClickListener);
// Show the custom action bar view and hide the normal Home icon and title.
- actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM
- | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
+ actionBar.setDisplayShowTitleEnabled(false);
+ actionBar.setDisplayShowHomeEnabled(false);
+ actionBar.setDisplayShowCustomEnabled(true);
actionBar.setCustomView(customActionBarView);
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
index ea4ca377c..82bb473f6 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -55,6 +55,7 @@ public class KeychainContract {
interface ApiAppsColumns {
String PACKAGE_NAME = "package_name";
+ String PACKAGE_SIGNATURE = "package_signature";
String KEY_ID = "key_id"; // not a database id
String ENCRYPTION_ALGORITHM = "encryption_algorithm";
String HASH_ALORITHM = "hash_algorithm";
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 0f962967d..60c5c91a8 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -31,7 +31,7 @@ import android.provider.BaseColumns;
public class KeychainDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "apg.db";
- private static final int DATABASE_VERSION = 5;
+ private static final int DATABASE_VERSION = 6;
public interface Tables {
String KEY_RINGS = "key_rings";
@@ -66,9 +66,10 @@ public class KeychainDatabase extends SQLiteOpenHelper {
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.KEY_ID + " INT64, "
- + ApiAppsColumns.ENCRYPTION_ALGORITHM + " INTEGER, " + ApiAppsColumns.HASH_ALORITHM
- + " INTEGER, " + ApiAppsColumns.COMPRESSION + " INTEGER)";
+ + ApiAppsColumns.PACKAGE_NAME + " TEXT UNIQUE, " + ApiAppsColumns.PACKAGE_SIGNATURE
+ + " BLOB, " + ApiAppsColumns.KEY_ID + " INT64, " + ApiAppsColumns.ENCRYPTION_ALGORITHM
+ + " INTEGER, " + ApiAppsColumns.HASH_ALORITHM + " INTEGER, "
+ + ApiAppsColumns.COMPRESSION + " INTEGER)";
KeychainDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -110,6 +111,10 @@ public class KeychainDatabase extends SQLiteOpenHelper {
break;
case 4:
db.execSQL(CREATE_API_APPS);
+ case 5:
+ // new column: package_signature
+ db.execSQL("DROP TABLE IF EXISTS " + Tables.API_APPS);
+ db.execSQL(CREATE_API_APPS);
default:
break;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 7ef61c15b..f12048277 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -742,6 +742,7 @@ public class ProviderHelper {
private static ContentValues contentValueForApiApps(AppSettings appSettings) {
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());
@@ -770,6 +771,8 @@ public class ProviderHelper {
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)));
@@ -781,4 +784,26 @@ public class ProviderHelper {
return settings;
}
+
+ public static byte[] getApiAppSignature(Context context, String packageName) {
+ Uri queryUri = KeychainContract.ApiApps.buildByPackageNameUri(packageName);
+
+ String[] projection = new String[] { ApiApps.PACKAGE_SIGNATURE };
+
+ ContentResolver cr = context.getContentResolver();
+ Cursor cursor = cr.query(queryUri, projection, null, null, null);
+
+ byte[] signature = null;
+ if (cursor != null && cursor.moveToFirst()) {
+ int signatureCol = 0;
+
+ signature = cursor.getBlob(signatureCol);
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ return signature;
+ }
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java
new file mode 100644
index 000000000..cef002265
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java
@@ -0,0 +1,10 @@
+package org.sufficientlysecure.keychain.service.exception;
+
+public class WrongPackageSignatureException extends Exception {
+
+ private static final long serialVersionUID = -8294642703122196028L;
+
+ public WrongPackageSignatureException(String message) {
+ super(message);
+ }
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java
index 381a4065c..9da4c8392 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java
@@ -23,6 +23,7 @@ import org.sufficientlysecure.keychain.Id;
public class AppSettings {
private String packageName;
+ private byte[] packageSignature;
private long keyId = Id.key.none;
private int encryptionAlgorithm;
private int hashAlgorithm;
@@ -32,9 +33,10 @@ public class AppSettings {
}
- public AppSettings(String packageName) {
+ public AppSettings(String packageName, byte[] packageSignature) {
super();
this.packageName = packageName;
+ this.packageSignature = packageSignature;
// defaults:
this.encryptionAlgorithm = PGPEncryptedData.AES_256;
this.hashAlgorithm = HashAlgorithmTags.SHA512;
@@ -49,6 +51,14 @@ public class AppSettings {
this.packageName = packageName;
}
+ public byte[] getPackageSignature() {
+ return packageSignature;
+ }
+
+ public void setPackageSignature(byte[] packageSignature) {
+ this.packageSignature = packageSignature;
+ }
+
public long getKeyId() {
return keyId;
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
index 7b04d3da6..4f1bedb6f 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
@@ -41,7 +41,7 @@ public class AppSettingsActivity extends SherlockFragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Inflate a "Done" custom action bar view to serve as the "Up" affordance.
+ // Inflate a "Done" custom action bar
ActionBarHelper.setDoneView(getSupportActionBar(), R.string.api_settings_save,
new View.OnClickListener() {
@Override
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
index 942f8eba8..e592f5d57 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
@@ -17,8 +17,12 @@
package org.sufficientlysecure.keychain.service.remote;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@@ -67,6 +71,8 @@ public class AppSettingsFragment extends Fragment {
private Spinner mEncryptionAlgorithm;
private Spinner mHashAlgorithm;
private Spinner mCompression;
+ private TextView mPackageName;
+ private TextView mPackageSignature;
KeyValueSpinnerAdapter encryptionAdapter;
KeyValueSpinnerAdapter hashAdapter;
@@ -79,6 +85,19 @@ public class AppSettingsFragment extends Fragment {
public void setAppSettings(AppSettings appSettings) {
this.appSettings = 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);
+ }
+
updateSelectedKeyView(appSettings.getKeyId());
mEncryptionAlgorithm.setSelection(encryptionAdapter.getPosition(appSettings
.getEncryptionAlgorithm()));
@@ -110,6 +129,8 @@ public class AppSettingsFragment extends Fragment {
.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);
AlgorithmNames algorithmNames = new AlgorithmNames(getActivity());
@@ -182,7 +203,7 @@ public class AppSettingsFragment extends Fragment {
public void onClick(View v) {
if (mAdvancedSettingsContainer.getVisibility() == View.VISIBLE) {
mAdvancedSettingsContainer.startAnimation(invisibleAnimation);
- mAdvancedSettingsContainer.setVisibility(View.INVISIBLE);
+ mAdvancedSettingsContainer.setVisibility(View.GONE);
mAdvancedSettingsButton.setText(R.string.api_settings_show_advanced);
} else {
mAdvancedSettingsContainer.startAnimation(visibleAnimation);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java
index 4e8c4678a..bc513d532 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java
@@ -18,18 +18,25 @@
package org.sufficientlysecure.keychain.service.remote;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
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.service.exception.WrongPackageSignatureException;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.PausableThreadPoolExecutor;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -38,7 +45,7 @@ import android.os.Message;
import android.os.Messenger;
/**
- * Abstract service for remote APIs that handle app registration and user input.
+ * Abstract service class for remote APIs that handle app registration and user input.
*/
public abstract class RemoteService extends Service {
Context mContext;
@@ -98,32 +105,61 @@ public abstract class RemoteService extends Service {
* @param r
*/
protected void checkAndEnqueue(Runnable r) {
- if (isCallerAllowed(false)) {
- mThreadPool.execute(r);
-
- Log.d(Constants.TAG, "Enqueued runnable…");
- } else {
- String[] callingPackages = getPackageManager()
- .getPackagesForUid(Binder.getCallingUid());
-
- Log.e(Constants.TAG, "Not allowed to use service! Starting activity for registration!");
- Bundle extras = new Bundle();
- // TODO: currently simply uses first entry
- extras.putString(RemoteServiceActivity.EXTRA_PACKAGE_NAME, callingPackages[0]);
-
- RegisterActivityCallback callback = new RegisterActivityCallback();
-
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_REGISTER, callback, extras);
-
- if (callback.isAllowed()) {
+ try {
+ if (isCallerAllowed(false)) {
mThreadPool.execute(r);
+
Log.d(Constants.TAG, "Enqueued runnable…");
} else {
- Log.d(Constants.TAG, "User disallowed app!");
+ String[] callingPackages = getPackageManager().getPackagesForUid(
+ Binder.getCallingUid());
+ // TODO: currently simply uses first entry
+ String packageName = callingPackages[0];
+
+ byte[] packageSignature;
+ try {
+ packageSignature = getPackageSignature(packageName);
+ } catch (NameNotFoundException e) {
+ Log.e(Constants.TAG, "Should not happen, returning!", e);
+ return;
+ }
+ Log.e(Constants.TAG,
+ "Not allowed to use service! Starting activity for registration!");
+ Bundle extras = new Bundle();
+ extras.putString(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
+ extras.putByteArray(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature);
+ RegisterActivityCallback callback = new RegisterActivityCallback();
+
+ pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_REGISTER, callback,
+ extras);
+
+ if (callback.isAllowed()) {
+ mThreadPool.execute(r);
+ Log.d(Constants.TAG, "Enqueued runnable…");
+ } else {
+ Log.d(Constants.TAG, "User disallowed app!");
+ }
}
+ } catch (WrongPackageSignatureException e) {
+ Log.e(Constants.TAG, e.getMessage());
+
+ Bundle extras = new Bundle();
+ extras.putString(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
+ getString(R.string.api_error_wrong_signature));
+ pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_ERROR_MESSAGE, null, extras);
}
}
+ private byte[] getPackageSignature(String packageName) throws NameNotFoundException {
+ PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName,
+ PackageManager.GET_SIGNATURES);
+ Signature[] signatures = pkgInfo.signatures;
+ // TODO: Only first signature?!
+ byte[] packageSignature = signatures[0].toByteArray();
+
+ return packageSignature;
+ }
+
/**
* Locks current thread and pauses execution of runnables and starts activity for user input
*
@@ -200,15 +236,25 @@ public abstract class RemoteService extends Service {
packageName = msg.getData().getString(PACKAGE_NAME);
// resume threads
- if (isPackageAllowed(packageName, false)) {
- synchronized (userInputLock) {
- userInputLock.notifyAll();
+ try {
+ if (isPackageAllowed(packageName)) {
+ synchronized (userInputLock) {
+ userInputLock.notifyAll();
+ }
+ mThreadPool.resume();
+ } else {
+ // Should not happen!
+ Log.e(Constants.TAG, "Should not happen! Emergency shutdown!");
+ mThreadPool.shutdownNow();
}
- mThreadPool.resume();
- } else {
- // Should not happen!
- Log.e(Constants.TAG, "Should not happen! Emergency shutdown!");
- mThreadPool.shutdownNow();
+ } catch (WrongPackageSignatureException e) {
+ Log.e(Constants.TAG, e.getMessage());
+
+ Bundle extras = new Bundle();
+ extras.putString(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
+ getString(R.string.api_error_wrong_signature));
+ pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_ERROR_MESSAGE, null,
+ extras);
}
} else {
allowed = false;
@@ -230,15 +276,28 @@ public abstract class RemoteService extends Service {
* @param allowOnlySelf
* allow only Keychain app itself
* @return true if process is allowed to use this service
+ * @throws WrongPackageSignatureException
*/
- private boolean isCallerAllowed(boolean allowOnlySelf) {
- String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
+ private boolean isCallerAllowed(boolean allowOnlySelf) throws WrongPackageSignatureException {
+ return isUidAllowed(Binder.getCallingUid(), allowOnlySelf);
+ }
+
+ private boolean isUidAllowed(int uid, boolean allowOnlySelf)
+ throws WrongPackageSignatureException {
+ if (android.os.Process.myUid() == uid) {
+ return true;
+ }
+ if (allowOnlySelf) { // barrier
+ return false;
+ }
+
+ String[] callingPackages = getPackageManager().getPackagesForUid(uid);
// is calling package allowed to use this service?
for (int i = 0; i < callingPackages.length; i++) {
String currentPkg = callingPackages[i];
- if (isPackageAllowed(currentPkg, allowOnlySelf)) {
+ if (isPackageAllowed(currentPkg)) {
return true;
}
}
@@ -248,28 +307,39 @@ public abstract class RemoteService extends Service {
}
/**
- * Checks if packageName is a registered app for the API.
+ * Checks if packageName is a registered app for the API. Does not return true for own package!
*
* @param packageName
- * @param allowOnlySelf
- * allow only Keychain app itself
* @return
+ * @throws WrongPackageSignatureException
*/
- private boolean isPackageAllowed(String packageName, boolean allowOnlySelf) {
+ private boolean isPackageAllowed(String packageName) throws WrongPackageSignatureException {
Log.d(Constants.TAG, "packageName: " + packageName);
- ArrayList<String> allowedPkgs = ProviderHelper.getRegisteredApiApps(mContext);
+ ArrayList<String> allowedPkgs = ProviderHelper.getRegisteredApiApps(this);
Log.d(Constants.TAG, "allowed: " + allowedPkgs);
// check if package is allowed to use our service
- if (allowedPkgs.contains(packageName) && (!allowOnlySelf)) {
+ if (allowedPkgs.contains(packageName)) {
Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName);
- return true;
- } else if (Constants.PACKAGE_NAME.equals(packageName)) {
- Log.d(Constants.TAG, "Package is OpenPGP Keychain! -> allowed!");
+ // check package signature
+ byte[] currentSig;
+ try {
+ currentSig = getPackageSignature(packageName);
+ } catch (NameNotFoundException e) {
+ throw new WrongPackageSignatureException(e.getMessage());
+ }
- return true;
+ byte[] storedSig = ProviderHelper.getApiAppSignature(this, packageName);
+ if (Arrays.equals(currentSig, storedSig)) {
+ Log.d(Constants.TAG,
+ "Package signature is correct! (equals signature from database)");
+ return true;
+ } else {
+ throw new WrongPackageSignatureException(
+ "PACKAGE NOT ALLOWED! Signature wrong! (Signature not equals signature from database)");
+ }
}
return false;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
index 2c4bb4e97..de07989d8 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
@@ -48,6 +48,8 @@ public class RemoteServiceActivity extends SherlockFragmentActivity {
+ "API_ACTIVITY_CACHE_PASSPHRASE";
public static final String ACTION_SELECT_PUB_KEYS = Constants.INTENT_PREFIX
+ "API_ACTIVITY_SELECT_PUB_KEYS";
+ public static final String ACTION_ERROR_MESSAGE = Constants.INTENT_PREFIX
+ + "API_ACTIVITY_ERROR_MESSAGE";
public static final String EXTRA_MESSENGER = "messenger";
@@ -55,10 +57,13 @@ public class RemoteServiceActivity extends SherlockFragmentActivity {
public static final String EXTRA_SECRET_KEY_ID = "secret_key_id";
// register action
public static final String EXTRA_PACKAGE_NAME = "package_name";
+ public static final String EXTRA_PACKAGE_SIGNATURE = "package_signature";
// 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";
public static final String EXTRA_DUBLICATE_USER_IDS = "dublicate_user_ids";
+ // error message
+ public static final String EXTRA_ERROR_MESSAGE = "error_message";
private Messenger mMessenger;
@@ -110,6 +115,7 @@ public class RemoteServiceActivity extends SherlockFragmentActivity {
*/
if (ACTION_REGISTER.equals(action)) {
final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
+ final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
// Inflate a "Done"/"Cancel" custom action bar view
ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.api_register_allow,
@@ -166,7 +172,7 @@ public class RemoteServiceActivity extends SherlockFragmentActivity {
mSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById(
R.id.api_app_settings_fragment);
- AppSettings settings = new AppSettings(packageName);
+ AppSettings settings = new AppSettings(packageName, packageSignature);
mSettingsFragment.setAppSettings(settings);
} else if (ACTION_CACHE_PASSPHRASE.equals(action)) {
long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID);
@@ -269,6 +275,27 @@ public class RemoteServiceActivity extends SherlockFragmentActivity {
getSupportFragmentManager().beginTransaction()
.add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit();
}
+ } else if (ACTION_ERROR_MESSAGE.equals(action)) {
+ String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE);
+
+ String text = new String();
+ text += "<font color=\"red\">" + errorMessage + "</font>";
+
+ // Inflate a "Done" custom action bar view
+ ActionBarHelper.setDoneView(getSupportActionBar(), R.string.btn_okay,
+ new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+
+ setContentView(R.layout.api_app_error_message);
+
+ // set text on view
+ HtmlTextView textView = (HtmlTextView) findViewById(R.id.api_app_error_message_text);
+ textView.setHtmlFromString(text);
} else {
Log.e(Constants.TAG, "Wrong action!");
finish();
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 1e62d06e3..7abee78f3 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -58,10 +58,8 @@ import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
-import android.widget.TextView;
import android.widget.Toast;
-import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
public class EditKeyActivity extends SherlockFragmentActivity {
@@ -81,8 +79,6 @@ public class EditKeyActivity extends SherlockFragmentActivity {
public static final String RESULT_EXTRA_MASTER_KEY_ID = "master_key_id";
public static final String RESULT_EXTRA_USER_ID = "user_id";
- private ActionBar mActionBar;
-
private PGPSecretKeyRing mKeyRing = null;
private SectionView mUserIdsView;
@@ -107,26 +103,15 @@ public class EditKeyActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Inflate a "Done"/"Cancel" custom action bar view
- final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext()
- .getSystemService(LAYOUT_INFLATER_SERVICE);
- final View customActionBarView = inflater.inflate(
- R.layout.actionbar_custom_view_done_cancel, null);
-
- ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text))
- .setText(R.string.btn_save);
- customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
+ // Inflate a "Done"/"Cancel" custom action bar
+ ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_save,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// save
saveClicked();
}
- });
- ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text))
- .setText(R.string.btn_do_not_save);
- customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
- new View.OnClickListener() {
+ }, R.string.btn_do_not_save, new View.OnClickListener() {
@Override
public void onClick(View v) {
// cancel
@@ -134,21 +119,8 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
});
- // Show the custom action bar view and hide the normal Home icon and title.
- final ActionBar actionBar = getSupportActionBar();
- actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM
- | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
- actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
-
setContentView(R.layout.edit_key);
- mActionBar = getSupportActionBar();
- mActionBar.setDisplayShowTitleEnabled(true);
-
- // set actionbar without home button if called from another app
- ActionBarHelper.setBackButton(this);
-
// find views
mChangePassPhrase = (Button) findViewById(R.id.edit_key_btn_change_pass_phrase);
mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase);
@@ -201,8 +173,6 @@ public class EditKeyActivity extends SherlockFragmentActivity {
private void handleActionCreateKey(Intent intent) {
Bundle extras = intent.getExtras();
- mActionBar.setTitle(R.string.title_create_key);
-
mCurrentPassPhrase = "";
if (extras != null) {
@@ -330,8 +300,6 @@ public class EditKeyActivity extends SherlockFragmentActivity {
private void handleActionEditKey(Intent intent) {
Bundle extras = intent.getExtras();
- mActionBar.setTitle(R.string.title_edit_key);
-
if (extras != null) {
if (extras.containsKey(EXTRA_MASTER_CAN_SIGN)) {
masterCanSign = extras.getBoolean(EXTRA_MASTER_CAN_SIGN);
diff --git a/README.md b/README.md
index 459809fc4..601d4710c 100644
--- a/README.md
+++ b/README.md
@@ -9,36 +9,27 @@ see http://sufficientlysecure.org/keychain
Translations are managed at Transifex, please contribute there at https://www.transifex.com/projects/p/openpgp-keychain/
-# Build
+## Code Contributions
+
+Fork OpenPGP Keychain and do a pull request. I will help with occuring problems and merge your changes back into the main project.
+I am happy about every code contribution and appreciate your effort to help us developing OpenPGP Keychain :)
## Build with Gradle
1. Have Android SDK "tools", "platform-tools", and "build-tools" directories in your PATH (http://developer.android.com/sdk/index.html)
2. Export ANDROID_HOME pointing to your Android SDK
-3. Install gradle
-4. Execute ``gradle wrapper`` (http://www.gradle.org/docs/current/userguide/gradle_wrapper.html)
-5. Execute ``./gradlew build``
-
-## Build with Ant
-
-1. Have Android SDK "tools" directory in your PATH (http://developer.android.com/sdk/index.html)
-2. Execute ``android update project -p OpenPGP-Keychain``
-3. Execute ``android update project -p libraries/ActionBarSherlock``
-3. Execute ``android update project -p libraries/HtmlTextView``
-3. Execute ``cd OpenPGP-Kechain``, ``ant debug``
-
-# Contribute
-
-Fork OpenPGP Keychain and do a merge request. I will merge your changes back into the main project.
+3. Download Android Support Repository, and Google Repository using Android SDK Manager
+4. Execute ``./gradlew build``
## Development with Eclipse
Android Studio is currently not supported or recommended!
1. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/ActionBarSherlock"
-1. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/HtmlTextView"
-2. File -> Import -> Android -> Existing Android Code Into Workspace, choose "OpenPGP-Keychain"
-3. OpenPGP-Kechain can now be build
+2. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/HtmlTextView"
+3. File -> Import -> Android -> Existing Android Code Into Workspace, choose "libraries/pinned-section-listview/library"
+4. File -> Import -> Android -> Existing Android Code Into Workspace, choose "OpenPGP-Keychain"
+5. OpenPGP-Kechain can now be build
# Keychain API
@@ -220,6 +211,10 @@ Some parts (older parts and some libraries are Apache License v2, MIT X11 Licens
* ZXing QRCode Integration
http://code.google.com/p/zxing/
Apache License v2
+
+* pinned-section-listview
+ https://github.com/beworker/pinned-section-listview
+ Apache License v2
## Images
diff --git a/Resources/Graphics/icon_googlecode.png b/Resources/Graphics/icon_googlecode.png
deleted file mode 100644
index 33acccfd3..000000000
--- a/Resources/Graphics/icon_googlecode.png
+++ /dev/null
Binary files differ
diff --git a/Resources/Graphics/dashboard_decrypt_default.svg b/Resources/graphics/dashboard_decrypt_default.svg
index 1b934251f..1b934251f 100644
--- a/Resources/Graphics/dashboard_decrypt_default.svg
+++ b/Resources/graphics/dashboard_decrypt_default.svg
diff --git a/Resources/Graphics/dashboard_decrypt_pressed.svg b/Resources/graphics/dashboard_decrypt_pressed.svg
index 1795a58ed..1795a58ed 100644
--- a/Resources/Graphics/dashboard_decrypt_pressed.svg
+++ b/Resources/graphics/dashboard_decrypt_pressed.svg
diff --git a/Resources/Graphics/dashboard_encrypt_default.svg b/Resources/graphics/dashboard_encrypt_default.svg
index 13ba746d3..13ba746d3 100644
--- a/Resources/Graphics/dashboard_encrypt_default.svg
+++ b/Resources/graphics/dashboard_encrypt_default.svg
diff --git a/Resources/Graphics/dashboard_encrypt_pressed.svg b/Resources/graphics/dashboard_encrypt_pressed.svg
index c0e58d848..c0e58d848 100644
--- a/Resources/Graphics/dashboard_encrypt_pressed.svg
+++ b/Resources/graphics/dashboard_encrypt_pressed.svg
diff --git a/Resources/Graphics/dashboard_help_default.svg b/Resources/graphics/dashboard_help_default.svg
index 9031729a3..9031729a3 100755
--- a/Resources/Graphics/dashboard_help_default.svg
+++ b/Resources/graphics/dashboard_help_default.svg
diff --git a/Resources/Graphics/dashboard_help_pressed.svg b/Resources/graphics/dashboard_help_pressed.svg
index 1e22f4679..1e22f4679 100644
--- a/Resources/Graphics/dashboard_help_pressed.svg
+++ b/Resources/graphics/dashboard_help_pressed.svg
diff --git a/Resources/Graphics/dashboard_import_default.svg b/Resources/graphics/dashboard_import_default.svg
index f59856e13..f59856e13 100644
--- a/Resources/Graphics/dashboard_import_default.svg
+++ b/Resources/graphics/dashboard_import_default.svg
diff --git a/Resources/Graphics/dashboard_import_pressed.svg b/Resources/graphics/dashboard_import_pressed.svg
index 34cba7aab..34cba7aab 100644
--- a/Resources/Graphics/dashboard_import_pressed.svg
+++ b/Resources/graphics/dashboard_import_pressed.svg
diff --git a/Resources/Graphics/dashboard_manage_keys_default.svg b/Resources/graphics/dashboard_manage_keys_default.svg
index b292673da..b292673da 100644
--- a/Resources/Graphics/dashboard_manage_keys_default.svg
+++ b/Resources/graphics/dashboard_manage_keys_default.svg
diff --git a/Resources/Graphics/dashboard_manage_keys_pressed.svg b/Resources/graphics/dashboard_manage_keys_pressed.svg
index a8eeb8cff..a8eeb8cff 100644
--- a/Resources/Graphics/dashboard_manage_keys_pressed.svg
+++ b/Resources/graphics/dashboard_manage_keys_pressed.svg
diff --git a/Resources/Graphics/dashboard_my_keys_default.svg b/Resources/graphics/dashboard_my_keys_default.svg
index 3f509c6f8..3f509c6f8 100644
--- a/Resources/Graphics/dashboard_my_keys_default.svg
+++ b/Resources/graphics/dashboard_my_keys_default.svg
diff --git a/Resources/Graphics/dashboard_my_keys_pressed.svg b/Resources/graphics/dashboard_my_keys_pressed.svg
index 5d84e1131..5d84e1131 100644
--- a/Resources/Graphics/dashboard_my_keys_pressed.svg
+++ b/Resources/graphics/dashboard_my_keys_pressed.svg
diff --git a/Resources/Graphics/dashboard_scan_qrcode_default.svg b/Resources/graphics/dashboard_scan_qrcode_default.svg
index bc49aa6a6..bc49aa6a6 100644
--- a/Resources/Graphics/dashboard_scan_qrcode_default.svg
+++ b/Resources/graphics/dashboard_scan_qrcode_default.svg
diff --git a/Resources/Graphics/dashboard_scan_qrcode_pressed.svg b/Resources/graphics/dashboard_scan_qrcode_pressed.svg
index c1bd869ac..c1bd869ac 100644
--- a/Resources/Graphics/dashboard_scan_qrcode_pressed.svg
+++ b/Resources/graphics/dashboard_scan_qrcode_pressed.svg
diff --git a/Resources/Graphics/icon_google_play.png b/Resources/graphics/icon.png
index d5d86ebbc..d5d86ebbc 100644
--- a/Resources/Graphics/icon_google_play.png
+++ b/Resources/graphics/icon.png
Binary files differ
diff --git a/Resources/Graphics/icon.svg b/Resources/graphics/icon.svg
index f07999465..f07999465 100644
--- a/Resources/Graphics/icon.svg
+++ b/Resources/graphics/icon.svg
diff --git a/Resources/Graphics/icon_sizes.txt b/Resources/graphics/icon_sizes.txt
index 2e960f6fd..2e960f6fd 100644
--- a/Resources/Graphics/icon_sizes.txt
+++ b/Resources/graphics/icon_sizes.txt
diff --git a/Resources/Graphics/key.svg b/Resources/graphics/key.svg
index 0fc167869..0fc167869 100644
--- a/Resources/Graphics/key.svg
+++ b/Resources/graphics/key.svg
diff --git a/Resources/Graphics/kgpg_key2_kopete.svgz b/Resources/graphics/kgpg_key2_kopete.svgz
index 2d43afb83..2d43afb83 100644
--- a/Resources/Graphics/kgpg_key2_kopete.svgz
+++ b/Resources/graphics/kgpg_key2_kopete.svgz
Binary files differ
diff --git a/Resources/graphics/update-icon.sh b/Resources/graphics/update-icon.sh
new file mode 100755
index 000000000..307541f2c
--- /dev/null
+++ b/Resources/graphics/update-icon.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+APP_DIR=../../OpenPGP-Keychain
+LDPI_DIR=$APP_DIR/res/drawable-ldpi
+MDPI_DIR=$APP_DIR/res/drawable-mdpi
+HDPI_DIR=$APP_DIR/res/drawable-hdpi
+XDPI_DIR=$APP_DIR/res/drawable-xhdpi
+XXDPI_DIR=$APP_DIR/res/drawable-xxhdpi
+XXXDPI_DIR=$APP_DIR/res/drawable-xxxhdpi
+PLAY_DIR=./
+
+
+# Launcher Icon:
+# -----------------------
+# ldpi: 36x36
+# mdpi: 48x48
+# hdpi: 72x72
+# xhdpi: 96x96
+# xxhdpi: 144x144.
+# xxxhdpi 192x192.
+# google play: 512x512
+
+NAME="icon"
+
+inkscape -w 36 -h 36 -e "$LDPI_DIR/$NAME.png" $NAME.svg
+inkscape -w 48 -h 48 -e "$MDPI_DIR/$NAME.png" $NAME.svg
+inkscape -w 72 -h 72 -e "$HDPI_DIR/$NAME.png" $NAME.svg
+inkscape -w 96 -h 96 -e "$XDPI_DIR/$NAME.png" $NAME.svg
+inkscape -w 144 -h 144 -e "$XXDPI_DIR/$NAME.png" $NAME.svg
+inkscape -w 192 -h 192 -e "$XXXDPI_DIR/$NAME.png" $NAME.svg
+inkscape -w 512 -h 512 -e "$PLAY_DIR/$NAME.png" $NAME.svg
+
diff --git a/Resources/Screenshots/screenshot1.png b/Resources/screenshots/screenshot1.png
index 9a546d45b..9a546d45b 100644
--- a/Resources/Screenshots/screenshot1.png
+++ b/Resources/screenshots/screenshot1.png
Binary files differ
diff --git a/Resources/Screenshots/screenshot2.png b/Resources/screenshots/screenshot2.png
index e9fa49d45..e9fa49d45 100644
--- a/Resources/Screenshots/screenshot2.png
+++ b/Resources/screenshots/screenshot2.png
Binary files differ
diff --git a/Resources/Screenshots/screenshot3.png b/Resources/screenshots/screenshot3.png
index aaec9cdb7..aaec9cdb7 100644
--- a/Resources/Screenshots/screenshot3.png
+++ b/Resources/screenshots/screenshot3.png
Binary files differ
diff --git a/Resources/Screenshots/screenshot4.png b/Resources/screenshots/screenshot4.png
index efe44a396..efe44a396 100644
--- a/Resources/Screenshots/screenshot4.png
+++ b/Resources/screenshots/screenshot4.png
Binary files differ
diff --git a/Resources/Screenshots/screenshot5.png b/Resources/screenshots/screenshot5.png
index 9356ca106..9356ca106 100644
--- a/Resources/Screenshots/screenshot5.png
+++ b/Resources/screenshots/screenshot5.png
Binary files differ
diff --git a/build.gradle b/build.gradle
index 63ba66abf..06c57cd0b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.5.+'
+ classpath 'com.android.tools.build:gradle:0.6.3'
}
}
@@ -15,5 +15,5 @@ allprojects {
}
task wrapper(type: Wrapper) {
- gradleVersion = '1.6'
+ gradleVersion = '1.8'
}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..667288ad6
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..f984ebc0a
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Dec 30 23:22:47 CET 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.8-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 000000000..91a7e269e
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 000000000..aec99730b
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/libraries/HtmlTextView/build.gradle b/libraries/HtmlTextView/build.gradle
index 40a586dab..1fd554404 100644
--- a/libraries/HtmlTextView/build.gradle
+++ b/libraries/HtmlTextView/build.gradle
@@ -3,7 +3,7 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.5.+'
+ classpath 'com.android.tools.build:gradle:0.6.3'
}
}
diff --git a/settings.gradle b/settings.gradle
index 08454c958..2e582798c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,4 @@
include ':OpenPGP-Keychain'
include ':libraries:ActionBarSherlock'
-include ':libraries:HtmlTextView' \ No newline at end of file
+include ':libraries:HtmlTextView'
+include ':libraries:pinned-section-listview:library' \ No newline at end of file