From 7939aaaa440f84a0df5524f8a1a1c04dd569eedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 14 Feb 2014 02:33:21 +0100 Subject: Introducing new ParcelFileDescriptor pipes --- OpenPGP-Keychain-API/example-app/build.gradle | 3 +- .../example-app/src/main/AndroidManifest.xml | 2 +- .../keychain/demo/OpenPgpProviderActivity.java | 332 +++++++++++---------- .../src/main/res/xml/base_preference.xml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- .../libraries/keychain-api-library/build.gradle | 1 + .../src/main/AndroidManifest.xml | 2 +- .../openpgp/IOpenPgpKeyIdsCallback.aidl | 2 +- .../org/openintents/openpgp/IOpenPgpService.aidl | 46 ++- .../aidl/org/openintents/openpgp/OpenPgpError.aidl | 2 +- .../openpgp/OpenPgpSignatureResult.aidl | 2 +- .../org/openintents/openpgp/OpenPgpConstants.java | 10 - .../java/org/openintents/openpgp/OpenPgpError.java | 11 +- .../org/openintents/openpgp/OpenPgpHelper.java | 52 ---- .../openintents/openpgp/OpenPgpListPreference.java | 201 ------------- .../openpgp/OpenPgpServiceConnection.java | 93 ------ .../openpgp/OpenPgpSignatureResult.java | 2 +- .../org/openintents/openpgp/util/OpenPgpApi.java | 83 ++++++ .../openintents/openpgp/util/OpenPgpConstants.java | 48 +++ .../openpgp/util/OpenPgpListPreference.java | 201 +++++++++++++ .../openpgp/util/OpenPgpServiceConnection.java | 93 ++++++ .../org/openintents/openpgp/util/OpenPgpUtils.java | 52 ++++ .../openpgp/util/ParcelFileDescriptorUtil.java | 104 +++++++ OpenPGP-Keychain/build.gradle | 2 +- OpenPGP-Keychain/src/main/AndroidManifest.xml | 2 +- .../keychain/service/remote/OpenPgpService.java | 280 ++++++++++------- .../keychain/service/remote/RemoteService.java | 4 - libraries/keychain-api-library/build.gradle | 12 +- .../src/main/AndroidManifest.xml | 2 +- .../openpgp/IOpenPgpKeyIdsCallback.aidl | 2 +- .../org/openintents/openpgp/IOpenPgpService.aidl | 46 ++- .../aidl/org/openintents/openpgp/OpenPgpError.aidl | 2 +- .../openpgp/OpenPgpSignatureResult.aidl | 2 +- .../org/openintents/openpgp/OpenPgpConstants.java | 10 - .../java/org/openintents/openpgp/OpenPgpError.java | 11 +- .../org/openintents/openpgp/OpenPgpHelper.java | 52 ---- .../openintents/openpgp/OpenPgpListPreference.java | 201 ------------- .../openpgp/OpenPgpServiceConnection.java | 93 ------ .../openpgp/OpenPgpSignatureResult.java | 2 +- .../org/openintents/openpgp/util/OpenPgpApi.java | 83 ++++++ .../openintents/openpgp/util/OpenPgpConstants.java | 48 +++ .../openpgp/util/OpenPgpListPreference.java | 201 +++++++++++++ .../openpgp/util/OpenPgpServiceConnection.java | 93 ++++++ .../org/openintents/openpgp/util/OpenPgpUtils.java | 52 ++++ .../openpgp/util/ParcelFileDescriptorUtil.java | 104 +++++++ 45 files changed, 1624 insertions(+), 1028 deletions(-) delete mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java delete mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java delete mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java delete mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpServiceConnection.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java delete mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java delete mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java delete mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java delete mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java create mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java create mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java create mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java create mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpServiceConnection.java create mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java create mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java diff --git a/OpenPGP-Keychain-API/example-app/build.gradle b/OpenPGP-Keychain-API/example-app/build.gradle index 99a09f094..373f83690 100644 --- a/OpenPGP-Keychain-API/example-app/build.gradle +++ b/OpenPGP-Keychain-API/example-app/build.gradle @@ -1,3 +1,4 @@ +// please leave this here, so this library builds on its own buildscript { repositories { mavenCentral() @@ -20,7 +21,7 @@ android { buildToolsVersion "19.0.1" defaultConfig { - minSdkVersion 8 + minSdkVersion 9 targetSdkVersion 19 } diff --git a/OpenPGP-Keychain-API/example-app/src/main/AndroidManifest.xml b/OpenPGP-Keychain-API/example-app/src/main/AndroidManifest.xml index 8b8c43776..39a990f72 100644 --- a/OpenPGP-Keychain-API/example-app/src/main/AndroidManifest.xml +++ b/OpenPGP-Keychain-API/example-app/src/main/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionName="1.1" > --> - diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl index 4ca356fad..f9b5fc453 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl index 8f9e8a0fd..ef390a7f6 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +20,35 @@ import org.openintents.openpgp.OpenPgpData; import org.openintents.openpgp.IOpenPgpCallback; import org.openintents.openpgp.IOpenPgpKeyIdsCallback; -/** - * All methods are oneway, which means they are asynchronous and non-blocking. - * Results are returned to the callback, which has to be implemented on client side. - */ interface IOpenPgpService { + /** + * Bundle params: + * api_version 1,2,3,... (current: 1) + * ascii_armor true/false (for output) + * key_ids long[] (for encrypt method) + * + * + * Bundle return: + * result_code RESULT_ERROR=0 (see error), RESULT_OK=1, RESULT_USER_INTERACTION_REQUIRED=2 (execute intent and do it again with params from intent) + * signature_result OpenPgpSignatureResult + * error OpenPgpError + * intent Intent + * + */ + + Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + + Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + + Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + + Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + + +/* + ------------------OLD-------------------------- +*/ /** * Sign * @@ -48,8 +71,9 @@ interface IOpenPgpService { * @param callback * Callback where to return results */ - oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); - + //oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); + + /** * Encrypt * @@ -74,7 +98,7 @@ interface IOpenPgpService { * @param callback * Callback where to return results */ - oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); + //oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); /** * Sign then encrypt @@ -100,7 +124,7 @@ interface IOpenPgpService { * @param callback * Callback where to return results */ - oneway void signAndEncrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); + //oneway void signAndEncrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); /** * Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted, @@ -126,7 +150,7 @@ interface IOpenPgpService { * @param callback * Callback where to return results */ - oneway void decryptAndVerify(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); + //oneway void decryptAndVerify(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); /** * Get available key ids based on given user ids @@ -138,6 +162,6 @@ interface IOpenPgpService { * @param callback * Callback where to return results (different type than callback in other functions!) */ - oneway void getKeyIds(in String[] ids, in boolean allowUserInteraction, in IOpenPgpKeyIdsCallback callback); + //oneway void getKeyIds(in String[] ids, in boolean allowUserInteraction, in IOpenPgpKeyIdsCallback callback); } \ No newline at end of file diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl index 7a6bed1e6..7f867653d 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl index e246792d0..d1d138b30 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java deleted file mode 100644 index b1ca1bfe6..000000000 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java +++ /dev/null @@ -1,10 +0,0 @@ -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/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java index f108d3169..4dd2cc641 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +20,13 @@ import android.os.Parcel; import android.os.Parcelable; public class OpenPgpError implements Parcelable { + public static final int CLIENT_SIDE_ERROR = -1; + public static final int GENERIC_ERROR = 0; - public static final int NO_OR_WRONG_PASSPHRASE = 1; - public static final int NO_USER_IDS = 2; - public static final int USER_INTERACTION_REQUIRED = 3; + public static final int INCOMPATIBLE_API_VERSIONS = 1; + + public static final int NO_OR_WRONG_PASSPHRASE = 2; + public static final int NO_USER_IDS = 3; int errorId; String message; diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java deleted file mode 100644 index 7305c47ce..000000000 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openintents.openpgp; - -import java.util.List; -import java.util.regex.Pattern; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.ResolveInfo; - -public class OpenPgpHelper { - private Context context; - - public static Pattern PGP_MESSAGE = Pattern.compile( - ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); - - public static Pattern PGP_SIGNED_MESSAGE = Pattern - .compile( - ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*", - Pattern.DOTALL); - - public OpenPgpHelper(Context context) { - super(); - this.context = context; - } - - public boolean isAvailable() { - Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT); - List resInfo = context.getPackageManager().queryIntentServices(intent, 0); - if (!resInfo.isEmpty()) { - return true; - } else { - return false; - } - } - -} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java deleted file mode 100644 index 4ddd97485..000000000 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openintents.openpgp; - -import java.util.ArrayList; -import java.util.List; - -import android.app.AlertDialog.Builder; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.graphics.drawable.Drawable; -import android.preference.DialogPreference; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ListAdapter; -import android.widget.TextView; - -public class OpenPgpListPreference extends DialogPreference { - ArrayList mProviderList = new ArrayList(); - private String mSelectedPackage; - - public OpenPgpListPreference(Context context, AttributeSet attrs) { - super(context, attrs); - - List 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())); - Drawable icon = resolveInfo.serviceInfo.loadIcon(context.getPackageManager()); - - // get api version - ServiceInfo si = resolveInfo.serviceInfo; - int apiVersion = si.metaData.getInt("api_version"); - - mProviderList.add(new OpenPgpProviderEntry(packageName, simpleName, icon, - apiVersion)); - } - } - } - - public OpenPgpListPreference(Context context) { - this(context, null); - } - - /** - * Can be used to add "no selection" - * - * @param packageName - * @param simpleName - * @param icon - */ - public void addProvider(int position, String packageName, String simpleName, Drawable icon, - int apiVersion) { - mProviderList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon, - apiVersion)); - } - - @Override - protected void onPrepareDialogBuilder(Builder builder) { - // Init ArrayAdapter with OpenPGP Providers - ListAdapter adapter = new ArrayAdapter(getContext(), - android.R.layout.select_dialog_singlechoice, android.R.id.text1, mProviderList) { - public View getView(int position, View convertView, ViewGroup parent) { - // User super class to create the View - View v = super.getView(position, convertView, parent); - TextView tv = (TextView) v.findViewById(android.R.id.text1); - - // Put the image on the TextView - tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon, null, - null, null); - - // 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 == OpenPgpConstants.REQUIRED_API_VERSION) { - tv.setEnabled(true); - } else { - tv.setEnabled(false); - tv.setText(tv.getText() + " (API v" + mProviderList.get(position).apiVersion - + ", needs v" + OpenPgpConstants.REQUIRED_API_VERSION + ")"); - } - - return v; - } - }; - - builder.setSingleChoiceItems(adapter, getIndexOfProviderList(getValue()), - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - mSelectedPackage = mProviderList.get(which).packageName; - - /* - * Clicking on an item simulates the positive button click, and dismisses - * the dialog. - */ - OpenPgpListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE); - dialog.dismiss(); - } - }); - - /* - * 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); - } - - @Override - protected void onDialogClosed(boolean positiveResult) { - super.onDialogClosed(positiveResult); - - if (positiveResult && (mSelectedPackage != null)) { - if (callChangeListener(mSelectedPackage)) { - setValue(mSelectedPackage); - } - } - } - - private int getIndexOfProviderList(String packageName) { - for (OpenPgpProviderEntry app : mProviderList) { - if (app.packageName.equals(packageName)) { - return mProviderList.indexOf(app); - } - } - - return -1; - } - - public void setValue(String packageName) { - mSelectedPackage = packageName; - persistString(packageName); - } - - public String getValue() { - return mSelectedPackage; - } - - public String getEntry() { - return getEntryByValue(mSelectedPackage); - } - - public String getEntryByValue(String packageName) { - for (OpenPgpProviderEntry app : mProviderList) { - if (app.packageName.equals(packageName)) { - return app.simpleName; - } - } - - return null; - } - - private static class OpenPgpProviderEntry { - private String packageName; - private String simpleName; - private Drawable icon; - private int apiVersion; - - public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon, - int apiVersion) { - this.packageName = packageName; - this.simpleName = simpleName; - this.icon = icon; - this.apiVersion = apiVersion; - } - - @Override - public String toString() { - return simpleName; - } - } -} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java deleted file mode 100644 index f7ba06aaf..000000000 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openintents.openpgp; - -import org.openintents.openpgp.IOpenPgpService; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; -import android.util.Log; - -public class OpenPgpServiceConnection { - private Context mApplicationContext; - - private IOpenPgpService mService; - private boolean mBound; - private String mCryptoProviderPackageName; - - public OpenPgpServiceConnection(Context context, String cryptoProviderPackageName) { - this.mApplicationContext = context.getApplicationContext(); - this.mCryptoProviderPackageName = cryptoProviderPackageName; - } - - public IOpenPgpService getService() { - return mService; - } - - public boolean isBound() { - return mBound; - } - - private ServiceConnection mCryptoServiceConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName name, IBinder service) { - mService = IOpenPgpService.Stub.asInterface(service); - Log.d(OpenPgpConstants.TAG, "connected to service"); - mBound = true; - } - - public void onServiceDisconnected(ComponentName name) { - mService = null; - Log.d(OpenPgpConstants.TAG, "disconnected from service"); - mBound = false; - } - }; - - /** - * If not already bound, bind! - * - * @return - */ - public boolean bindToService() { - if (mService == null && !mBound) { // if not already connected - try { - Log.d(OpenPgpConstants.TAG, "not bound yet"); - - Intent serviceIntent = new Intent(); - serviceIntent.setAction(IOpenPgpService.class.getName()); - serviceIntent.setPackage(mCryptoProviderPackageName); - mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection, - Context.BIND_AUTO_CREATE); - - return true; - } catch (Exception e) { - Log.d(OpenPgpConstants.TAG, "Exception on binding", e); - return false; - } - } else { - Log.d(OpenPgpConstants.TAG, "already bound"); - return true; - } - } - - public void unbindFromService() { - mApplicationContext.unbindService(mCryptoServiceConnection); - } - -} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java index 829f8f8cf..226eeacc2 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java new file mode 100644 index 000000000..6efb507c4 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import android.os.Bundle; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.util.Log; + +import org.openintents.openpgp.IOpenPgpService; +import org.openintents.openpgp.OpenPgpError; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class OpenPgpApi { + + IOpenPgpService mService; + + public OpenPgpApi(IOpenPgpService service) { + this.mService = service; + } + + public Bundle sign(InputStream is, final OutputStream os) { + try { + // send the input and output pfds + ParcelFileDescriptor input = ParcelFileDescriptorUtil.pipeFrom(is, + new ParcelFileDescriptorUtil.IThreadListener() { + + @Override + public void onThreadFinished(Thread thread) { + Log.d(OpenPgpConstants.TAG, "Copy to service finished"); + } + }); + ParcelFileDescriptor output = ParcelFileDescriptorUtil.pipeTo(os, + new ParcelFileDescriptorUtil.IThreadListener() { + + @Override + public void onThreadFinished(Thread thread) { + Log.d(OpenPgpConstants.TAG, "Service finished writing!"); + } + }); + + // blocks until result is ready + Bundle result = mService.sign(null, input, output); + // close() is required to halt the TransferThread + output.close(); + + return result; + } catch (RemoteException e) { + Log.e(OpenPgpConstants.TAG, "RemoteException", e); + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage())); + return result; + } catch (IOException e) { + Log.e(OpenPgpConstants.TAG, "IOException", e); + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage())); + return result; + } + } + + +} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java new file mode 100644 index 000000000..3dd9391d0 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +public class OpenPgpConstants { + + public static final String TAG = "OpenPgp API"; + + public static final int API_VERSION = 1; + public static final String SERVICE_INTENT = "org.openintents.openpgp.IOpenPgpService"; + + + /* Bundle params */ + public static final String PARAMS_API_VERSION = "api_version"; + // request ASCII Armor for output + // OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) + public static final String PARAMS_REQUEST_ASCII_ARMOR = "ascii_armor"; + // (for encrypt method) + public static final String PARAMS_KEY_IDS = "key_ids"; + + /* Bundle return */ + public static final String RESULT_CODE = "result_code"; + public static final String RESULT_SIGNATURE = "signature"; + public static final String RESULT_ERRORS = "error"; + public static final String RESULT_INTENT = "intent"; + + // get actual error object from RESULT_ERRORS + public static final int RESULT_CODE_ERROR = 0; + // success! + public static final int RESULT_CODE_SUCCESS = 1; + // execute intent and do it again with params from intent + public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2; + +} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java new file mode 100644 index 000000000..ea287a7a9 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import java.util.ArrayList; +import java.util.List; + +import android.app.AlertDialog.Builder; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.graphics.drawable.Drawable; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.TextView; + +public class OpenPgpListPreference extends DialogPreference { + ArrayList mProviderList = new ArrayList(); + private String mSelectedPackage; + + public OpenPgpListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + List 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())); + Drawable icon = resolveInfo.serviceInfo.loadIcon(context.getPackageManager()); + + // get api version + ServiceInfo si = resolveInfo.serviceInfo; + int apiVersion = si.metaData.getInt("api_version"); + + mProviderList.add(new OpenPgpProviderEntry(packageName, simpleName, icon, + apiVersion)); + } + } + } + + public OpenPgpListPreference(Context context) { + this(context, null); + } + + /** + * Can be used to add "no selection" + * + * @param packageName + * @param simpleName + * @param icon + */ + public void addProvider(int position, String packageName, String simpleName, Drawable icon, + int apiVersion) { + mProviderList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon, + apiVersion)); + } + + @Override + protected void onPrepareDialogBuilder(Builder builder) { + // Init ArrayAdapter with OpenPGP Providers + ListAdapter adapter = new ArrayAdapter(getContext(), + android.R.layout.select_dialog_singlechoice, android.R.id.text1, mProviderList) { + public View getView(int position, View convertView, ViewGroup parent) { + // User super class to create the View + View v = super.getView(position, convertView, parent); + TextView tv = (TextView) v.findViewById(android.R.id.text1); + + // Put the image on the TextView + tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon, null, + null, null); + + // 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 == OpenPgpConstants.API_VERSION) { + tv.setEnabled(true); + } else { + tv.setEnabled(false); + tv.setText(tv.getText() + " (API v" + mProviderList.get(position).apiVersion + + ", needs v" + OpenPgpConstants.API_VERSION + ")"); + } + + return v; + } + }; + + builder.setSingleChoiceItems(adapter, getIndexOfProviderList(getValue()), + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + mSelectedPackage = mProviderList.get(which).packageName; + + /* + * Clicking on an item simulates the positive button click, and dismisses + * the dialog. + */ + OpenPgpListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE); + dialog.dismiss(); + } + }); + + /* + * 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); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + + if (positiveResult && (mSelectedPackage != null)) { + if (callChangeListener(mSelectedPackage)) { + setValue(mSelectedPackage); + } + } + } + + private int getIndexOfProviderList(String packageName) { + for (OpenPgpProviderEntry app : mProviderList) { + if (app.packageName.equals(packageName)) { + return mProviderList.indexOf(app); + } + } + + return -1; + } + + public void setValue(String packageName) { + mSelectedPackage = packageName; + persistString(packageName); + } + + public String getValue() { + return mSelectedPackage; + } + + public String getEntry() { + return getEntryByValue(mSelectedPackage); + } + + public String getEntryByValue(String packageName) { + for (OpenPgpProviderEntry app : mProviderList) { + if (app.packageName.equals(packageName)) { + return app.simpleName; + } + } + + return null; + } + + private static class OpenPgpProviderEntry { + private String packageName; + private String simpleName; + private Drawable icon; + private int apiVersion; + + public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon, + int apiVersion) { + this.packageName = packageName; + this.simpleName = simpleName; + this.icon = icon; + this.apiVersion = apiVersion; + } + + @Override + public String toString() { + return simpleName; + } + } +} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpServiceConnection.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpServiceConnection.java new file mode 100644 index 000000000..780b4606b --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpServiceConnection.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import org.openintents.openpgp.IOpenPgpService; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +public class OpenPgpServiceConnection { + private Context mApplicationContext; + + private IOpenPgpService mService; + private boolean mBound; + private String mCryptoProviderPackageName; + + public OpenPgpServiceConnection(Context context, String cryptoProviderPackageName) { + this.mApplicationContext = context.getApplicationContext(); + this.mCryptoProviderPackageName = cryptoProviderPackageName; + } + + public IOpenPgpService getService() { + return mService; + } + + public boolean isBound() { + return mBound; + } + + private ServiceConnection mCryptoServiceConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + mService = IOpenPgpService.Stub.asInterface(service); + Log.d(OpenPgpConstants.TAG, "connected to service"); + mBound = true; + } + + public void onServiceDisconnected(ComponentName name) { + mService = null; + Log.d(OpenPgpConstants.TAG, "disconnected from service"); + mBound = false; + } + }; + + /** + * If not already bound, bind! + * + * @return + */ + public boolean bindToService() { + if (mService == null && !mBound) { // if not already connected + try { + Log.d(OpenPgpConstants.TAG, "not bound yet"); + + Intent serviceIntent = new Intent(); + serviceIntent.setAction(IOpenPgpService.class.getName()); + serviceIntent.setPackage(mCryptoProviderPackageName); + mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection, + Context.BIND_AUTO_CREATE); + + return true; + } catch (Exception e) { + Log.d(OpenPgpConstants.TAG, "Exception on binding", e); + return false; + } + } else { + Log.d(OpenPgpConstants.TAG, "already bound"); + return true; + } + } + + public void unbindFromService() { + mApplicationContext.unbindService(mCryptoServiceConnection); + } + +} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java new file mode 100644 index 000000000..6dbf76897 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import java.util.List; +import java.util.regex.Pattern; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; + +public class OpenPgpUtils { + private Context context; + + public static Pattern PGP_MESSAGE = Pattern.compile( + ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); + + public static Pattern PGP_SIGNED_MESSAGE = Pattern + .compile( + ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*", + Pattern.DOTALL); + + public OpenPgpUtils(Context context) { + super(); + this.context = context; + } + + public boolean isAvailable() { + Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT); + List resInfo = context.getPackageManager().queryIntentServices(intent, 0); + if (!resInfo.isEmpty()) { + return true; + } else { + return false; + } + } + +} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java new file mode 100644 index 000000000..20f8c36f3 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * 2013 Flow (http://stackoverflow.com/questions/18212152/transfer-inputstream-to-another-service-across-process-boundaries-with-parcelf) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class ParcelFileDescriptorUtil { + + public interface IThreadListener { + void onThreadFinished(final Thread thread); + } + + public static ParcelFileDescriptor pipeFrom(InputStream inputStream, IThreadListener listener) + throws IOException { + ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); + ParcelFileDescriptor readSide = pipe[0]; + ParcelFileDescriptor writeSide = pipe[1]; + + // start the transfer thread + new TransferThread(inputStream, new ParcelFileDescriptor.AutoCloseOutputStream(writeSide), + listener) + .start(); + + return readSide; + } + + public static ParcelFileDescriptor pipeTo(OutputStream outputStream, IThreadListener listener) + throws IOException { + ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); + ParcelFileDescriptor readSide = pipe[0]; + ParcelFileDescriptor writeSide = pipe[1]; + + // start the transfer thread + new TransferThread(new ParcelFileDescriptor.AutoCloseInputStream(readSide), outputStream, + listener) + .start(); + + return writeSide; + } + + static class TransferThread extends Thread { + final InputStream mIn; + final OutputStream mOut; + final IThreadListener mListener; + + TransferThread(InputStream in, OutputStream out, IThreadListener listener) { + super("ParcelFileDescriptor Transfer Thread"); + mIn = in; + mOut = out; + mListener = listener; + setDaemon(true); + } + + @Override + public void run() { + byte[] buf = new byte[1024]; + int len; + + try { + while ((len = mIn.read(buf)) > 0) { + mOut.write(buf, 0, len); + } + mOut.flush(); // just to be safe + } catch (IOException e) { + Log.e(OpenPgpConstants.TAG, "TransferThread" + getId() + ": writing failed", e); + } finally { + try { + mIn.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + mOut.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (mListener != null) { + Log.d(OpenPgpConstants.TAG, "TransferThread " + getId() + " finished!"); + mListener.onThreadFinished(this); + } + } + } +} \ No newline at end of file diff --git a/OpenPGP-Keychain/build.gradle b/OpenPGP-Keychain/build.gradle index 66c6a0e8f..28e8c37b1 100644 --- a/OpenPGP-Keychain/build.gradle +++ b/OpenPGP-Keychain/build.gradle @@ -20,7 +20,7 @@ android { buildToolsVersion "19.0.1" defaultConfig { - minSdkVersion 8 + minSdkVersion 9 targetSdkVersion 19 } diff --git a/OpenPGP-Keychain/src/main/AndroidManifest.xml b/OpenPGP-Keychain/src/main/AndroidManifest.xml index 6de35571f..45b034b97 100644 --- a/OpenPGP-Keychain/src/main/AndroidManifest.xml +++ b/OpenPGP-Keychain/src/main/AndroidManifest.xml @@ -30,7 +30,7 @@ --> diff --git a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl index 4ca356fad..f9b5fc453 100644 --- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl +++ b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl index 8f9e8a0fd..ef390a7f6 100644 --- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl +++ b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +20,35 @@ import org.openintents.openpgp.OpenPgpData; import org.openintents.openpgp.IOpenPgpCallback; import org.openintents.openpgp.IOpenPgpKeyIdsCallback; -/** - * All methods are oneway, which means they are asynchronous and non-blocking. - * Results are returned to the callback, which has to be implemented on client side. - */ interface IOpenPgpService { + /** + * Bundle params: + * api_version 1,2,3,... (current: 1) + * ascii_armor true/false (for output) + * key_ids long[] (for encrypt method) + * + * + * Bundle return: + * result_code RESULT_ERROR=0 (see error), RESULT_OK=1, RESULT_USER_INTERACTION_REQUIRED=2 (execute intent and do it again with params from intent) + * signature_result OpenPgpSignatureResult + * error OpenPgpError + * intent Intent + * + */ + + Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + + Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + + Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + + Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + + +/* + ------------------OLD-------------------------- +*/ /** * Sign * @@ -48,8 +71,9 @@ interface IOpenPgpService { * @param callback * Callback where to return results */ - oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); - + //oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); + + /** * Encrypt * @@ -74,7 +98,7 @@ interface IOpenPgpService { * @param callback * Callback where to return results */ - oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); + //oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); /** * Sign then encrypt @@ -100,7 +124,7 @@ interface IOpenPgpService { * @param callback * Callback where to return results */ - oneway void signAndEncrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); + //oneway void signAndEncrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); /** * Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted, @@ -126,7 +150,7 @@ interface IOpenPgpService { * @param callback * Callback where to return results */ - oneway void decryptAndVerify(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); + //oneway void decryptAndVerify(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); /** * Get available key ids based on given user ids @@ -138,6 +162,6 @@ interface IOpenPgpService { * @param callback * Callback where to return results (different type than callback in other functions!) */ - oneway void getKeyIds(in String[] ids, in boolean allowUserInteraction, in IOpenPgpKeyIdsCallback callback); + //oneway void getKeyIds(in String[] ids, in boolean allowUserInteraction, in IOpenPgpKeyIdsCallback callback); } \ No newline at end of file diff --git a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl index 7a6bed1e6..7f867653d 100644 --- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl +++ b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl index e246792d0..d1d138b30 100644 --- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl +++ b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java deleted file mode 100644 index b1ca1bfe6..000000000 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java +++ /dev/null @@ -1,10 +0,0 @@ -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/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java index f108d3169..4dd2cc641 100644 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +20,13 @@ import android.os.Parcel; import android.os.Parcelable; public class OpenPgpError implements Parcelable { + public static final int CLIENT_SIDE_ERROR = -1; + public static final int GENERIC_ERROR = 0; - public static final int NO_OR_WRONG_PASSPHRASE = 1; - public static final int NO_USER_IDS = 2; - public static final int USER_INTERACTION_REQUIRED = 3; + public static final int INCOMPATIBLE_API_VERSIONS = 1; + + public static final int NO_OR_WRONG_PASSPHRASE = 2; + public static final int NO_USER_IDS = 3; int errorId; String message; diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java deleted file mode 100644 index 7305c47ce..000000000 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openintents.openpgp; - -import java.util.List; -import java.util.regex.Pattern; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.ResolveInfo; - -public class OpenPgpHelper { - private Context context; - - public static Pattern PGP_MESSAGE = Pattern.compile( - ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); - - public static Pattern PGP_SIGNED_MESSAGE = Pattern - .compile( - ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*", - Pattern.DOTALL); - - public OpenPgpHelper(Context context) { - super(); - this.context = context; - } - - public boolean isAvailable() { - Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT); - List resInfo = context.getPackageManager().queryIntentServices(intent, 0); - if (!resInfo.isEmpty()) { - return true; - } else { - return false; - } - } - -} diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java deleted file mode 100644 index 4ddd97485..000000000 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openintents.openpgp; - -import java.util.ArrayList; -import java.util.List; - -import android.app.AlertDialog.Builder; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.graphics.drawable.Drawable; -import android.preference.DialogPreference; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ListAdapter; -import android.widget.TextView; - -public class OpenPgpListPreference extends DialogPreference { - ArrayList mProviderList = new ArrayList(); - private String mSelectedPackage; - - public OpenPgpListPreference(Context context, AttributeSet attrs) { - super(context, attrs); - - List 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())); - Drawable icon = resolveInfo.serviceInfo.loadIcon(context.getPackageManager()); - - // get api version - ServiceInfo si = resolveInfo.serviceInfo; - int apiVersion = si.metaData.getInt("api_version"); - - mProviderList.add(new OpenPgpProviderEntry(packageName, simpleName, icon, - apiVersion)); - } - } - } - - public OpenPgpListPreference(Context context) { - this(context, null); - } - - /** - * Can be used to add "no selection" - * - * @param packageName - * @param simpleName - * @param icon - */ - public void addProvider(int position, String packageName, String simpleName, Drawable icon, - int apiVersion) { - mProviderList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon, - apiVersion)); - } - - @Override - protected void onPrepareDialogBuilder(Builder builder) { - // Init ArrayAdapter with OpenPGP Providers - ListAdapter adapter = new ArrayAdapter(getContext(), - android.R.layout.select_dialog_singlechoice, android.R.id.text1, mProviderList) { - public View getView(int position, View convertView, ViewGroup parent) { - // User super class to create the View - View v = super.getView(position, convertView, parent); - TextView tv = (TextView) v.findViewById(android.R.id.text1); - - // Put the image on the TextView - tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon, null, - null, null); - - // 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 == OpenPgpConstants.REQUIRED_API_VERSION) { - tv.setEnabled(true); - } else { - tv.setEnabled(false); - tv.setText(tv.getText() + " (API v" + mProviderList.get(position).apiVersion - + ", needs v" + OpenPgpConstants.REQUIRED_API_VERSION + ")"); - } - - return v; - } - }; - - builder.setSingleChoiceItems(adapter, getIndexOfProviderList(getValue()), - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - mSelectedPackage = mProviderList.get(which).packageName; - - /* - * Clicking on an item simulates the positive button click, and dismisses - * the dialog. - */ - OpenPgpListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE); - dialog.dismiss(); - } - }); - - /* - * 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); - } - - @Override - protected void onDialogClosed(boolean positiveResult) { - super.onDialogClosed(positiveResult); - - if (positiveResult && (mSelectedPackage != null)) { - if (callChangeListener(mSelectedPackage)) { - setValue(mSelectedPackage); - } - } - } - - private int getIndexOfProviderList(String packageName) { - for (OpenPgpProviderEntry app : mProviderList) { - if (app.packageName.equals(packageName)) { - return mProviderList.indexOf(app); - } - } - - return -1; - } - - public void setValue(String packageName) { - mSelectedPackage = packageName; - persistString(packageName); - } - - public String getValue() { - return mSelectedPackage; - } - - public String getEntry() { - return getEntryByValue(mSelectedPackage); - } - - public String getEntryByValue(String packageName) { - for (OpenPgpProviderEntry app : mProviderList) { - if (app.packageName.equals(packageName)) { - return app.simpleName; - } - } - - return null; - } - - private static class OpenPgpProviderEntry { - private String packageName; - private String simpleName; - private Drawable icon; - private int apiVersion; - - public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon, - int apiVersion) { - this.packageName = packageName; - this.simpleName = simpleName; - this.icon = icon; - this.apiVersion = apiVersion; - } - - @Override - public String toString() { - return simpleName; - } - } -} diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java deleted file mode 100644 index f7ba06aaf..000000000 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openintents.openpgp; - -import org.openintents.openpgp.IOpenPgpService; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; -import android.util.Log; - -public class OpenPgpServiceConnection { - private Context mApplicationContext; - - private IOpenPgpService mService; - private boolean mBound; - private String mCryptoProviderPackageName; - - public OpenPgpServiceConnection(Context context, String cryptoProviderPackageName) { - this.mApplicationContext = context.getApplicationContext(); - this.mCryptoProviderPackageName = cryptoProviderPackageName; - } - - public IOpenPgpService getService() { - return mService; - } - - public boolean isBound() { - return mBound; - } - - private ServiceConnection mCryptoServiceConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName name, IBinder service) { - mService = IOpenPgpService.Stub.asInterface(service); - Log.d(OpenPgpConstants.TAG, "connected to service"); - mBound = true; - } - - public void onServiceDisconnected(ComponentName name) { - mService = null; - Log.d(OpenPgpConstants.TAG, "disconnected from service"); - mBound = false; - } - }; - - /** - * If not already bound, bind! - * - * @return - */ - public boolean bindToService() { - if (mService == null && !mBound) { // if not already connected - try { - Log.d(OpenPgpConstants.TAG, "not bound yet"); - - Intent serviceIntent = new Intent(); - serviceIntent.setAction(IOpenPgpService.class.getName()); - serviceIntent.setPackage(mCryptoProviderPackageName); - mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection, - Context.BIND_AUTO_CREATE); - - return true; - } catch (Exception e) { - Log.d(OpenPgpConstants.TAG, "Exception on binding", e); - return false; - } - } else { - Log.d(OpenPgpConstants.TAG, "already bound"); - return true; - } - } - - public void unbindFromService() { - mApplicationContext.unbindService(mCryptoServiceConnection); - } - -} diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java index 829f8f8cf..226eeacc2 100644 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2014 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java new file mode 100644 index 000000000..6efb507c4 --- /dev/null +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import android.os.Bundle; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.util.Log; + +import org.openintents.openpgp.IOpenPgpService; +import org.openintents.openpgp.OpenPgpError; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class OpenPgpApi { + + IOpenPgpService mService; + + public OpenPgpApi(IOpenPgpService service) { + this.mService = service; + } + + public Bundle sign(InputStream is, final OutputStream os) { + try { + // send the input and output pfds + ParcelFileDescriptor input = ParcelFileDescriptorUtil.pipeFrom(is, + new ParcelFileDescriptorUtil.IThreadListener() { + + @Override + public void onThreadFinished(Thread thread) { + Log.d(OpenPgpConstants.TAG, "Copy to service finished"); + } + }); + ParcelFileDescriptor output = ParcelFileDescriptorUtil.pipeTo(os, + new ParcelFileDescriptorUtil.IThreadListener() { + + @Override + public void onThreadFinished(Thread thread) { + Log.d(OpenPgpConstants.TAG, "Service finished writing!"); + } + }); + + // blocks until result is ready + Bundle result = mService.sign(null, input, output); + // close() is required to halt the TransferThread + output.close(); + + return result; + } catch (RemoteException e) { + Log.e(OpenPgpConstants.TAG, "RemoteException", e); + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage())); + return result; + } catch (IOException e) { + Log.e(OpenPgpConstants.TAG, "IOException", e); + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage())); + return result; + } + } + + +} diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java new file mode 100644 index 000000000..3dd9391d0 --- /dev/null +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +public class OpenPgpConstants { + + public static final String TAG = "OpenPgp API"; + + public static final int API_VERSION = 1; + public static final String SERVICE_INTENT = "org.openintents.openpgp.IOpenPgpService"; + + + /* Bundle params */ + public static final String PARAMS_API_VERSION = "api_version"; + // request ASCII Armor for output + // OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) + public static final String PARAMS_REQUEST_ASCII_ARMOR = "ascii_armor"; + // (for encrypt method) + public static final String PARAMS_KEY_IDS = "key_ids"; + + /* Bundle return */ + public static final String RESULT_CODE = "result_code"; + public static final String RESULT_SIGNATURE = "signature"; + public static final String RESULT_ERRORS = "error"; + public static final String RESULT_INTENT = "intent"; + + // get actual error object from RESULT_ERRORS + public static final int RESULT_CODE_ERROR = 0; + // success! + public static final int RESULT_CODE_SUCCESS = 1; + // execute intent and do it again with params from intent + public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2; + +} diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java new file mode 100644 index 000000000..ea287a7a9 --- /dev/null +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import java.util.ArrayList; +import java.util.List; + +import android.app.AlertDialog.Builder; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.graphics.drawable.Drawable; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.TextView; + +public class OpenPgpListPreference extends DialogPreference { + ArrayList mProviderList = new ArrayList(); + private String mSelectedPackage; + + public OpenPgpListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + List 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())); + Drawable icon = resolveInfo.serviceInfo.loadIcon(context.getPackageManager()); + + // get api version + ServiceInfo si = resolveInfo.serviceInfo; + int apiVersion = si.metaData.getInt("api_version"); + + mProviderList.add(new OpenPgpProviderEntry(packageName, simpleName, icon, + apiVersion)); + } + } + } + + public OpenPgpListPreference(Context context) { + this(context, null); + } + + /** + * Can be used to add "no selection" + * + * @param packageName + * @param simpleName + * @param icon + */ + public void addProvider(int position, String packageName, String simpleName, Drawable icon, + int apiVersion) { + mProviderList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon, + apiVersion)); + } + + @Override + protected void onPrepareDialogBuilder(Builder builder) { + // Init ArrayAdapter with OpenPGP Providers + ListAdapter adapter = new ArrayAdapter(getContext(), + android.R.layout.select_dialog_singlechoice, android.R.id.text1, mProviderList) { + public View getView(int position, View convertView, ViewGroup parent) { + // User super class to create the View + View v = super.getView(position, convertView, parent); + TextView tv = (TextView) v.findViewById(android.R.id.text1); + + // Put the image on the TextView + tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon, null, + null, null); + + // 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 == OpenPgpConstants.API_VERSION) { + tv.setEnabled(true); + } else { + tv.setEnabled(false); + tv.setText(tv.getText() + " (API v" + mProviderList.get(position).apiVersion + + ", needs v" + OpenPgpConstants.API_VERSION + ")"); + } + + return v; + } + }; + + builder.setSingleChoiceItems(adapter, getIndexOfProviderList(getValue()), + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + mSelectedPackage = mProviderList.get(which).packageName; + + /* + * Clicking on an item simulates the positive button click, and dismisses + * the dialog. + */ + OpenPgpListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE); + dialog.dismiss(); + } + }); + + /* + * 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); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + + if (positiveResult && (mSelectedPackage != null)) { + if (callChangeListener(mSelectedPackage)) { + setValue(mSelectedPackage); + } + } + } + + private int getIndexOfProviderList(String packageName) { + for (OpenPgpProviderEntry app : mProviderList) { + if (app.packageName.equals(packageName)) { + return mProviderList.indexOf(app); + } + } + + return -1; + } + + public void setValue(String packageName) { + mSelectedPackage = packageName; + persistString(packageName); + } + + public String getValue() { + return mSelectedPackage; + } + + public String getEntry() { + return getEntryByValue(mSelectedPackage); + } + + public String getEntryByValue(String packageName) { + for (OpenPgpProviderEntry app : mProviderList) { + if (app.packageName.equals(packageName)) { + return app.simpleName; + } + } + + return null; + } + + private static class OpenPgpProviderEntry { + private String packageName; + private String simpleName; + private Drawable icon; + private int apiVersion; + + public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon, + int apiVersion) { + this.packageName = packageName; + this.simpleName = simpleName; + this.icon = icon; + this.apiVersion = apiVersion; + } + + @Override + public String toString() { + return simpleName; + } + } +} diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpServiceConnection.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpServiceConnection.java new file mode 100644 index 000000000..780b4606b --- /dev/null +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpServiceConnection.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import org.openintents.openpgp.IOpenPgpService; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +public class OpenPgpServiceConnection { + private Context mApplicationContext; + + private IOpenPgpService mService; + private boolean mBound; + private String mCryptoProviderPackageName; + + public OpenPgpServiceConnection(Context context, String cryptoProviderPackageName) { + this.mApplicationContext = context.getApplicationContext(); + this.mCryptoProviderPackageName = cryptoProviderPackageName; + } + + public IOpenPgpService getService() { + return mService; + } + + public boolean isBound() { + return mBound; + } + + private ServiceConnection mCryptoServiceConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + mService = IOpenPgpService.Stub.asInterface(service); + Log.d(OpenPgpConstants.TAG, "connected to service"); + mBound = true; + } + + public void onServiceDisconnected(ComponentName name) { + mService = null; + Log.d(OpenPgpConstants.TAG, "disconnected from service"); + mBound = false; + } + }; + + /** + * If not already bound, bind! + * + * @return + */ + public boolean bindToService() { + if (mService == null && !mBound) { // if not already connected + try { + Log.d(OpenPgpConstants.TAG, "not bound yet"); + + Intent serviceIntent = new Intent(); + serviceIntent.setAction(IOpenPgpService.class.getName()); + serviceIntent.setPackage(mCryptoProviderPackageName); + mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection, + Context.BIND_AUTO_CREATE); + + return true; + } catch (Exception e) { + Log.d(OpenPgpConstants.TAG, "Exception on binding", e); + return false; + } + } else { + Log.d(OpenPgpConstants.TAG, "already bound"); + return true; + } + } + + public void unbindFromService() { + mApplicationContext.unbindService(mCryptoServiceConnection); + } + +} diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java new file mode 100644 index 000000000..6dbf76897 --- /dev/null +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import java.util.List; +import java.util.regex.Pattern; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; + +public class OpenPgpUtils { + private Context context; + + public static Pattern PGP_MESSAGE = Pattern.compile( + ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); + + public static Pattern PGP_SIGNED_MESSAGE = Pattern + .compile( + ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*", + Pattern.DOTALL); + + public OpenPgpUtils(Context context) { + super(); + this.context = context; + } + + public boolean isAvailable() { + Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT); + List resInfo = context.getPackageManager().queryIntentServices(intent, 0); + if (!resInfo.isEmpty()) { + return true; + } else { + return false; + } + } + +} diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java new file mode 100644 index 000000000..20f8c36f3 --- /dev/null +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * 2013 Flow (http://stackoverflow.com/questions/18212152/transfer-inputstream-to-another-service-across-process-boundaries-with-parcelf) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp.util; + +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class ParcelFileDescriptorUtil { + + public interface IThreadListener { + void onThreadFinished(final Thread thread); + } + + public static ParcelFileDescriptor pipeFrom(InputStream inputStream, IThreadListener listener) + throws IOException { + ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); + ParcelFileDescriptor readSide = pipe[0]; + ParcelFileDescriptor writeSide = pipe[1]; + + // start the transfer thread + new TransferThread(inputStream, new ParcelFileDescriptor.AutoCloseOutputStream(writeSide), + listener) + .start(); + + return readSide; + } + + public static ParcelFileDescriptor pipeTo(OutputStream outputStream, IThreadListener listener) + throws IOException { + ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); + ParcelFileDescriptor readSide = pipe[0]; + ParcelFileDescriptor writeSide = pipe[1]; + + // start the transfer thread + new TransferThread(new ParcelFileDescriptor.AutoCloseInputStream(readSide), outputStream, + listener) + .start(); + + return writeSide; + } + + static class TransferThread extends Thread { + final InputStream mIn; + final OutputStream mOut; + final IThreadListener mListener; + + TransferThread(InputStream in, OutputStream out, IThreadListener listener) { + super("ParcelFileDescriptor Transfer Thread"); + mIn = in; + mOut = out; + mListener = listener; + setDaemon(true); + } + + @Override + public void run() { + byte[] buf = new byte[1024]; + int len; + + try { + while ((len = mIn.read(buf)) > 0) { + mOut.write(buf, 0, len); + } + mOut.flush(); // just to be safe + } catch (IOException e) { + Log.e(OpenPgpConstants.TAG, "TransferThread" + getId() + ": writing failed", e); + } finally { + try { + mIn.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + mOut.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (mListener != null) { + Log.d(OpenPgpConstants.TAG, "TransferThread " + getId() + " finished!"); + mListener.onThreadFinished(this); + } + } + } +} \ No newline at end of file -- cgit v1.2.3 From ee2fec17597c35ad2329f44cc697e18e3e4169cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 14 Feb 2014 02:41:27 +0100 Subject: fix nullpointer --- .../src/main/java/org/openintents/openpgp/util/OpenPgpApi.java | 5 ++++- .../keychain/service/remote/OpenPgpService.java | 10 +++++++++- .../src/main/java/org/openintents/openpgp/util/OpenPgpApi.java | 5 ++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java index 6efb507c4..d490bca0c 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java @@ -56,8 +56,11 @@ public class OpenPgpApi { } }); + Bundle params = new Bundle(); + params.putInt(OpenPgpConstants.PARAMS_API_VERSION, OpenPgpConstants.API_VERSION); + // blocks until result is ready - Bundle result = mService.sign(null, input, output); + Bundle result = mService.sign(params, input, output); // close() is required to halt the TransferThread output.close(); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java index 9cdb12eda..006754bae 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java @@ -522,9 +522,17 @@ public class OpenPgpService extends RemoteService { public Bundle sign(Bundle params, final ParcelFileDescriptor input, final ParcelFileDescriptor output) { final AppSettings appSettings = getAppSettings(); - Bundle result = new Bundle(); + if (params == null) { + Bundle result = new Bundle(); + OpenPgpError error = new OpenPgpError(OpenPgpError.GENERIC_ERROR, "params Bundle required!"); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, error); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + return result; + } + if (params.getInt(OpenPgpConstants.PARAMS_API_VERSION) != OpenPgpConstants.API_VERSION) { // not compatible! + Bundle result = new Bundle(); OpenPgpError error = new OpenPgpError(OpenPgpError.INCOMPATIBLE_API_VERSIONS, "Incompatible API versions!"); result.putParcelable(OpenPgpConstants.RESULT_ERRORS, error); result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java index 6efb507c4..d490bca0c 100644 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java @@ -56,8 +56,11 @@ public class OpenPgpApi { } }); + Bundle params = new Bundle(); + params.putInt(OpenPgpConstants.PARAMS_API_VERSION, OpenPgpConstants.API_VERSION); + // blocks until result is ready - Bundle result = mService.sign(null, input, output); + Bundle result = mService.sign(params, input, output); // close() is required to halt the TransferThread output.close(); -- cgit v1.2.3 From acad2ba95723a940467e89a07e91498188a88745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 14 Feb 2014 13:40:24 +0100 Subject: PendingIntent to handle user input --- .../keychain/demo/OpenPgpProviderActivity.java | 87 +++++++++--- .../org/openintents/openpgp/IOpenPgpService.aidl | 151 ++++----------------- .../org/openintents/openpgp/util/OpenPgpApi.java | 123 +++++++++++++++-- .../openintents/openpgp/util/OpenPgpConstants.java | 2 +- OpenPGP-Keychain/src/main/AndroidManifest.xml | 7 +- .../keychain/service/KeychainIntentService.java | 2 +- .../keychain/service/remote/OpenPgpService.java | 79 +++++++---- .../service/remote/RemoteServiceActivity.java | 60 ++++---- .../keychain/ui/DecryptActivity.java | 2 +- .../keychain/ui/EncryptActivity.java | 2 +- OpenPGP-Keychain/src/main/res/values/strings.xml | 2 +- .../org/openintents/openpgp/IOpenPgpService.aidl | 151 ++++----------------- .../org/openintents/openpgp/util/OpenPgpApi.java | 123 +++++++++++++++-- .../openintents/openpgp/util/OpenPgpConstants.java | 2 +- 14 files changed, 444 insertions(+), 349 deletions(-) diff --git a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java index 81f9eee68..39843eb82 100644 --- a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java +++ b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java @@ -18,11 +18,14 @@ package org.sufficientlysecure.keychain.demo; import android.app.Activity; import android.app.AlertDialog; +import android.app.PendingIntent; import android.content.DialogInterface; import android.content.Intent; +import android.content.IntentSender; import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.v4.app.TaskStackBuilder; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -54,6 +57,11 @@ public class OpenPgpProviderActivity extends Activity { private OpenPgpServiceConnection mCryptoServiceConnection; + public static final int REQUEST_CODE_SIGN = 9910; + public static final int REQUEST_CODE_ENCRYPT = 9911; + public static final int REQUEST_CODE_SIGN_AND_ENC = 9912; + public static final int REQUEST_CODE_DECRYPT = 9913; + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -210,30 +218,60 @@ public class OpenPgpProviderActivity extends Activity { } public void signOnClick(View view) { + InputStream is = null; try { String inputStr = mMessage.getText().toString(); - InputStream is = new ByteArrayInputStream(inputStr.getBytes("UTF-8")); - - final ByteArrayOutputStream os = new ByteArrayOutputStream(); - - OpenPgpApi api = new OpenPgpApi(mCryptoServiceConnection.getService()); - api.sign(is, os); + is = new ByteArrayInputStream(inputStr.getBytes("UTF-8")); - Log.d(OpenPgpConstants.TAG, "Test #1 read result: " + os.toByteArray().length - + " str=" + os.toString("UTF-8")); - - mCiphertext.setText(os.toString("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } -// OpenPgpData input = new OpenPgpData(inputStr); + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + + OpenPgpApi api = new OpenPgpApi(mCryptoServiceConnection.getService()); + api.sign(new Bundle(), is, os, new OpenPgpApi.IOpenPgpCallback() { + @Override + public void onReturn(Bundle result) { + switch (result.getInt(OpenPgpConstants.RESULT_CODE)) { + case OpenPgpConstants.RESULT_CODE_SUCCESS: { + try { + Log.d(OpenPgpConstants.TAG, "result: " + os.toByteArray().length + + " str=" + os.toString("UTF-8")); + + mCiphertext.setText(os.toString("UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + break; + } + case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED: { + PendingIntent pi = result.getParcelable(OpenPgpConstants.RESULT_INTENT); + try { + OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(), + REQUEST_CODE_SIGN, null, // or new Intent() (in billing) + 0, 0, 0); + } catch (IntentSender.SendIntentException e) { + e.printStackTrace(); + } +// try { +// pi.send(OpenPgpProviderActivity.this, 42, null, new PendingIntent.OnFinished() { // -// try { -// mCryptoServiceConnection.getService().sign(input, -// new OpenPgpData(OpenPgpData.TYPE_STRING), encryptCallback); -// } catch (RemoteException e) { -// Log.e(Constants.TAG, "CryptoProviderDemo", e); -// } +// @Override +// public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras) { +// Log.d(Constants.TAG, "onSendFinished"); +// Log.d(Constants.TAG, "resultCode: " + resultCode); +// +// } +// }, null); +// } catch (PendingIntent.CanceledException e) { +// e.printStackTrace(); +// } + break; + } + } + } + }); + } public void signAndEncryptOnClick(View view) { @@ -258,6 +296,21 @@ public class OpenPgpProviderActivity extends Activity { // } } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { +// super.onActivityResult(requestCode, resultCode, data); + Log.d(Constants.TAG, "onActivityResult"); + switch (requestCode) { + case REQUEST_CODE_SIGN: { + Log.d(Constants.TAG, "resultCode: " + resultCode); + + if (resultCode == RESULT_OK) { + signOnClick(null); + } + } + } + } + @Override public void onDestroy() { super.onDestroy(); diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl index ef390a7f6..714ca040e 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl @@ -23,145 +23,52 @@ import org.openintents.openpgp.IOpenPgpKeyIdsCallback; interface IOpenPgpService { /** - * Bundle params: - * api_version 1,2,3,... (current: 1) - * ascii_armor true/false (for output) - * key_ids long[] (for encrypt method) + * General extras + * -------------- + * + * params: + * int api_version (current: 1) + * boolean ascii_armor true/false (for output) * * * Bundle return: - * result_code RESULT_ERROR=0 (see error), RESULT_OK=1, RESULT_USER_INTERACTION_REQUIRED=2 (execute intent and do it again with params from intent) - * signature_result OpenPgpSignatureResult - * error OpenPgpError - * intent Intent + * int result_code 0,1, or 2 (see OpenPgpConstants) + * OpenPgpSignatureResult signature_result + * OpenPgpError error + * Intent intent * */ - Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); - - Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); - - Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); - - Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); - - -/* - ------------------OLD-------------------------- -*/ /** - * Sign - * - * After successful signing, callback's onSuccess will contain the resulting output. + * sign only * - * @param input - * OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri - * @param output - * Request output format by defining OpenPgpData object - * - * new OpenPgpData(OpenPgpData.TYPE_STRING) - * Returns as String - * (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) - * new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY) - * Returns as byte[] - * new OpenPgpData(uri) - * Writes output to given Uri - * new OpenPgpData(fileDescriptor) - * Writes output to given ParcelFileDescriptor - * @param callback - * Callback where to return results + * params: + * String passphrase (optional) */ - //oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); - + Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); /** - * Encrypt - * - * After successful encryption, callback's onSuccess will contain the resulting output. - * - * @param input - * OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri - * @param output - * Request output format by defining OpenPgpData object - * - * new OpenPgpData(OpenPgpData.TYPE_STRING) - * Returns as String - * (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) - * new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY) - * Returns as byte[] - * new OpenPgpData(uri) - * 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 + * encrypt + * + * params: + * long[] key_ids + * or + * String[] user_ids (= emails of recipients) (if more than one key has this user_id, an Intent is returned) */ - //oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); - + Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + /** - * Sign then encrypt - * - * After successful signing and encryption, callback's onSuccess will contain the resulting output. + * sign and encrypt * - * @param input - * OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri - * @param output - * Request output format by defining OpenPgpData object - * - * new OpenPgpData(OpenPgpData.TYPE_STRING) - * Returns as String - * (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) - * new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY) - * Returns as byte[] - * new OpenPgpData(uri) - * 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 + * params: + * same as in encrypt() */ - //oneway void signAndEncrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); - + Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + /** * Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted, * and also signed-only input. - * - * 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 - * OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri - * @param output - * Request output format by defining OpenPgpData object - * - * new OpenPgpData(OpenPgpData.TYPE_STRING) - * Returns as String - * (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) - * new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY) - * Returns as byte[] - * new OpenPgpData(uri) - * Writes output to given Uri - * new OpenPgpData(fileDescriptor) - * Writes output to given ParcelFileDescriptor - * @param callback - * Callback where to return results */ - //oneway void decryptAndVerify(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); - - /** - * Get available key ids based on given user ids - * - * @param ids - * User Ids (emails) of recipients OR key ids - * @param allowUserInteraction - * Enable user interaction to lookup and import unknown keys - * @param callback - * Callback where to return results (different type than callback in other functions!) - */ - //oneway void getKeyIds(in String[] ids, in boolean allowUserInteraction, in IOpenPgpKeyIdsCallback callback); - + Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + } \ No newline at end of file diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java index d490bca0c..adb187c04 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java @@ -16,15 +16,14 @@ package org.openintents.openpgp.util; +import android.os.AsyncTask; import android.os.Bundle; import android.os.ParcelFileDescriptor; -import android.os.RemoteException; import android.util.Log; import org.openintents.openpgp.IOpenPgpService; import org.openintents.openpgp.OpenPgpError; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -32,11 +31,98 @@ public class OpenPgpApi { IOpenPgpService mService; + private static final int OPERATION_SIGN = 0; + private static final int OPERATION_ENCRYPT = 1; + private static final int OPERATION_SIGN_ENCRYPT = 2; + private static final int OPERATION_DECRYPT_VERIFY = 3; + public OpenPgpApi(IOpenPgpService service) { this.mService = service; } public Bundle sign(InputStream is, final OutputStream os) { + return executeApi(OPERATION_SIGN, new Bundle(), is, os); + } + + public Bundle sign(Bundle params, InputStream is, final OutputStream os) { + return executeApi(OPERATION_SIGN, params, is, os); + } + + public void sign(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) { + executeApiAsync(OPERATION_SIGN, params, is, os, callback); + } + + public Bundle encrypt(InputStream is, final OutputStream os) { + return executeApi(OPERATION_ENCRYPT, new Bundle(), is, os); + } + + public Bundle encrypt(Bundle params, InputStream is, final OutputStream os) { + return executeApi(OPERATION_ENCRYPT, params, is, os); + } + + public void encrypt(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) { + executeApiAsync(OPERATION_ENCRYPT, params, is, os, callback); + } + + public Bundle signAndEncrypt(InputStream is, final OutputStream os) { + return executeApi(OPERATION_SIGN_ENCRYPT, new Bundle(), is, os); + } + + public Bundle signAndEncrypt(Bundle params, InputStream is, final OutputStream os) { + return executeApi(OPERATION_SIGN_ENCRYPT, params, is, os); + } + + public void signAndEncrypt(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) { + executeApiAsync(OPERATION_SIGN_ENCRYPT, params, is, os, callback); + } + + public Bundle decryptAndVerify(InputStream is, final OutputStream os) { + return executeApi(OPERATION_DECRYPT_VERIFY, new Bundle(), is, os); + } + + public Bundle decryptAndVerify(Bundle params, InputStream is, final OutputStream os) { + return executeApi(OPERATION_DECRYPT_VERIFY, params, is, os); + } + + public void decryptAndVerify(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) { + executeApiAsync(OPERATION_DECRYPT_VERIFY, params, is, os, callback); + } + + public interface IOpenPgpCallback { + void onReturn(final Bundle result); + } + + private class OpenPgpAsyncTask extends AsyncTask { + int operationId; + Bundle params; + InputStream is; + OutputStream os; + IOpenPgpCallback callback; + + private OpenPgpAsyncTask(int operationId, Bundle params, InputStream is, OutputStream os, IOpenPgpCallback callback) { + this.operationId = operationId; + this.params = params; + this.is = is; + this.os = os; + this.callback = callback; + } + + @Override + protected Bundle doInBackground(Void... unused) { + return executeApi(operationId, params, is, os); + } + + protected void onPostExecute(Bundle result) { + callback.onReturn(result); + } + + } + + private void executeApiAsync(int operationId, Bundle params, InputStream is, OutputStream os, IOpenPgpCallback callback) { + new OpenPgpAsyncTask(operationId, params, is, os, callback).execute((Void[]) null); + } + + private Bundle executeApi(int operationId, Bundle params, InputStream is, OutputStream os) { try { // send the input and output pfds ParcelFileDescriptor input = ParcelFileDescriptorUtil.pipeFrom(is, @@ -56,24 +142,35 @@ public class OpenPgpApi { } }); - Bundle params = new Bundle(); params.putInt(OpenPgpConstants.PARAMS_API_VERSION, OpenPgpConstants.API_VERSION); + // default result is error + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + new OpenPgpError(OpenPgpError.GENERIC_ERROR, "This should never happen!")); + // blocks until result is ready - Bundle result = mService.sign(params, input, output); + switch (operationId) { + case OPERATION_SIGN: + result = mService.sign(params, input, output); + break; + case OPERATION_ENCRYPT: + result = mService.encrypt(params, input, output); + break; + case OPERATION_SIGN_ENCRYPT: + result = mService.signAndEncrypt(params, input, output); + break; + case OPERATION_DECRYPT_VERIFY: + result = mService.decryptAndVerify(params, input, output); + break; + } // close() is required to halt the TransferThread output.close(); return result; - } catch (RemoteException e) { - Log.e(OpenPgpConstants.TAG, "RemoteException", e); - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, - new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage())); - return result; - } catch (IOException e) { - Log.e(OpenPgpConstants.TAG, "IOException", e); + } catch (Exception e) { + Log.e(OpenPgpConstants.TAG, "Exception", e); Bundle result = new Bundle(); result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); result.putParcelable(OpenPgpConstants.RESULT_ERRORS, diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java index 3dd9391d0..1bf3d76a3 100644 --- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java @@ -42,7 +42,7 @@ public class OpenPgpConstants { public static final int RESULT_CODE_ERROR = 0; // success! public static final int RESULT_CODE_SUCCESS = 1; - // execute intent and do it again with params from intent + // executeServiceMethod intent and do it again with params from intent public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2; } diff --git a/OpenPGP-Keychain/src/main/AndroidManifest.xml b/OpenPGP-Keychain/src/main/AndroidManifest.xml index 45b034b97..ba2bd5571 100644 --- a/OpenPGP-Keychain/src/main/AndroidManifest.xml +++ b/OpenPGP-Keychain/src/main/AndroidManifest.xml @@ -362,10 +362,9 @@ + android:label="@string/app_name" /> + + Revoke access Package Name SHA-256 of Package Signature - The following application requests access to OpenPGP Keychain.\n\nAllow permanent access? + The following application requests access to OpenPGP Keychain.\n\nAllow access (you can revoke it later)? Allow access Disallow access Please select a key! diff --git a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl index ef390a7f6..714ca040e 100644 --- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl +++ b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl @@ -23,145 +23,52 @@ import org.openintents.openpgp.IOpenPgpKeyIdsCallback; interface IOpenPgpService { /** - * Bundle params: - * api_version 1,2,3,... (current: 1) - * ascii_armor true/false (for output) - * key_ids long[] (for encrypt method) + * General extras + * -------------- + * + * params: + * int api_version (current: 1) + * boolean ascii_armor true/false (for output) * * * Bundle return: - * result_code RESULT_ERROR=0 (see error), RESULT_OK=1, RESULT_USER_INTERACTION_REQUIRED=2 (execute intent and do it again with params from intent) - * signature_result OpenPgpSignatureResult - * error OpenPgpError - * intent Intent + * int result_code 0,1, or 2 (see OpenPgpConstants) + * OpenPgpSignatureResult signature_result + * OpenPgpError error + * Intent intent * */ - Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); - - Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); - - Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); - - Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); - - -/* - ------------------OLD-------------------------- -*/ /** - * Sign - * - * After successful signing, callback's onSuccess will contain the resulting output. + * sign only * - * @param input - * OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri - * @param output - * Request output format by defining OpenPgpData object - * - * new OpenPgpData(OpenPgpData.TYPE_STRING) - * Returns as String - * (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) - * new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY) - * Returns as byte[] - * new OpenPgpData(uri) - * Writes output to given Uri - * new OpenPgpData(fileDescriptor) - * Writes output to given ParcelFileDescriptor - * @param callback - * Callback where to return results + * params: + * String passphrase (optional) */ - //oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); - + Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); /** - * Encrypt - * - * After successful encryption, callback's onSuccess will contain the resulting output. - * - * @param input - * OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri - * @param output - * Request output format by defining OpenPgpData object - * - * new OpenPgpData(OpenPgpData.TYPE_STRING) - * Returns as String - * (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) - * new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY) - * Returns as byte[] - * new OpenPgpData(uri) - * 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 + * encrypt + * + * params: + * long[] key_ids + * or + * String[] user_ids (= emails of recipients) (if more than one key has this user_id, an Intent is returned) */ - //oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); - + Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + /** - * Sign then encrypt - * - * After successful signing and encryption, callback's onSuccess will contain the resulting output. + * sign and encrypt * - * @param input - * OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri - * @param output - * Request output format by defining OpenPgpData object - * - * new OpenPgpData(OpenPgpData.TYPE_STRING) - * Returns as String - * (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) - * new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY) - * Returns as byte[] - * new OpenPgpData(uri) - * 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 + * params: + * same as in encrypt() */ - //oneway void signAndEncrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback); - + Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + /** * Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted, * and also signed-only input. - * - * 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 - * OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri - * @param output - * Request output format by defining OpenPgpData object - * - * new OpenPgpData(OpenPgpData.TYPE_STRING) - * Returns as String - * (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53) - * new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY) - * Returns as byte[] - * new OpenPgpData(uri) - * Writes output to given Uri - * new OpenPgpData(fileDescriptor) - * Writes output to given ParcelFileDescriptor - * @param callback - * Callback where to return results */ - //oneway void decryptAndVerify(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback); - - /** - * Get available key ids based on given user ids - * - * @param ids - * User Ids (emails) of recipients OR key ids - * @param allowUserInteraction - * Enable user interaction to lookup and import unknown keys - * @param callback - * Callback where to return results (different type than callback in other functions!) - */ - //oneway void getKeyIds(in String[] ids, in boolean allowUserInteraction, in IOpenPgpKeyIdsCallback callback); - + Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output); + } \ No newline at end of file diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java index d490bca0c..adb187c04 100644 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java @@ -16,15 +16,14 @@ package org.openintents.openpgp.util; +import android.os.AsyncTask; import android.os.Bundle; import android.os.ParcelFileDescriptor; -import android.os.RemoteException; import android.util.Log; import org.openintents.openpgp.IOpenPgpService; import org.openintents.openpgp.OpenPgpError; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -32,11 +31,98 @@ public class OpenPgpApi { IOpenPgpService mService; + private static final int OPERATION_SIGN = 0; + private static final int OPERATION_ENCRYPT = 1; + private static final int OPERATION_SIGN_ENCRYPT = 2; + private static final int OPERATION_DECRYPT_VERIFY = 3; + public OpenPgpApi(IOpenPgpService service) { this.mService = service; } public Bundle sign(InputStream is, final OutputStream os) { + return executeApi(OPERATION_SIGN, new Bundle(), is, os); + } + + public Bundle sign(Bundle params, InputStream is, final OutputStream os) { + return executeApi(OPERATION_SIGN, params, is, os); + } + + public void sign(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) { + executeApiAsync(OPERATION_SIGN, params, is, os, callback); + } + + public Bundle encrypt(InputStream is, final OutputStream os) { + return executeApi(OPERATION_ENCRYPT, new Bundle(), is, os); + } + + public Bundle encrypt(Bundle params, InputStream is, final OutputStream os) { + return executeApi(OPERATION_ENCRYPT, params, is, os); + } + + public void encrypt(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) { + executeApiAsync(OPERATION_ENCRYPT, params, is, os, callback); + } + + public Bundle signAndEncrypt(InputStream is, final OutputStream os) { + return executeApi(OPERATION_SIGN_ENCRYPT, new Bundle(), is, os); + } + + public Bundle signAndEncrypt(Bundle params, InputStream is, final OutputStream os) { + return executeApi(OPERATION_SIGN_ENCRYPT, params, is, os); + } + + public void signAndEncrypt(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) { + executeApiAsync(OPERATION_SIGN_ENCRYPT, params, is, os, callback); + } + + public Bundle decryptAndVerify(InputStream is, final OutputStream os) { + return executeApi(OPERATION_DECRYPT_VERIFY, new Bundle(), is, os); + } + + public Bundle decryptAndVerify(Bundle params, InputStream is, final OutputStream os) { + return executeApi(OPERATION_DECRYPT_VERIFY, params, is, os); + } + + public void decryptAndVerify(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) { + executeApiAsync(OPERATION_DECRYPT_VERIFY, params, is, os, callback); + } + + public interface IOpenPgpCallback { + void onReturn(final Bundle result); + } + + private class OpenPgpAsyncTask extends AsyncTask { + int operationId; + Bundle params; + InputStream is; + OutputStream os; + IOpenPgpCallback callback; + + private OpenPgpAsyncTask(int operationId, Bundle params, InputStream is, OutputStream os, IOpenPgpCallback callback) { + this.operationId = operationId; + this.params = params; + this.is = is; + this.os = os; + this.callback = callback; + } + + @Override + protected Bundle doInBackground(Void... unused) { + return executeApi(operationId, params, is, os); + } + + protected void onPostExecute(Bundle result) { + callback.onReturn(result); + } + + } + + private void executeApiAsync(int operationId, Bundle params, InputStream is, OutputStream os, IOpenPgpCallback callback) { + new OpenPgpAsyncTask(operationId, params, is, os, callback).execute((Void[]) null); + } + + private Bundle executeApi(int operationId, Bundle params, InputStream is, OutputStream os) { try { // send the input and output pfds ParcelFileDescriptor input = ParcelFileDescriptorUtil.pipeFrom(is, @@ -56,24 +142,35 @@ public class OpenPgpApi { } }); - Bundle params = new Bundle(); params.putInt(OpenPgpConstants.PARAMS_API_VERSION, OpenPgpConstants.API_VERSION); + // default result is error + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + new OpenPgpError(OpenPgpError.GENERIC_ERROR, "This should never happen!")); + // blocks until result is ready - Bundle result = mService.sign(params, input, output); + switch (operationId) { + case OPERATION_SIGN: + result = mService.sign(params, input, output); + break; + case OPERATION_ENCRYPT: + result = mService.encrypt(params, input, output); + break; + case OPERATION_SIGN_ENCRYPT: + result = mService.signAndEncrypt(params, input, output); + break; + case OPERATION_DECRYPT_VERIFY: + result = mService.decryptAndVerify(params, input, output); + break; + } // close() is required to halt the TransferThread output.close(); return result; - } catch (RemoteException e) { - Log.e(OpenPgpConstants.TAG, "RemoteException", e); - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, - new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage())); - return result; - } catch (IOException e) { - Log.e(OpenPgpConstants.TAG, "IOException", e); + } catch (Exception e) { + Log.e(OpenPgpConstants.TAG, "Exception", e); Bundle result = new Bundle(); result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); result.putParcelable(OpenPgpConstants.RESULT_ERRORS, diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java index 3dd9391d0..1bf3d76a3 100644 --- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java +++ b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpConstants.java @@ -42,7 +42,7 @@ public class OpenPgpConstants { public static final int RESULT_CODE_ERROR = 0; // success! public static final int RESULT_CODE_SUCCESS = 1; - // execute intent and do it again with params from intent + // executeServiceMethod intent and do it again with params from intent public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2; } -- cgit v1.2.3 From d6953745810bd4c6dee3bfefb538236b2b7bdbb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 14 Feb 2014 17:01:17 +0100 Subject: conversion of other methods --- .../keychain/demo/OpenPgpProviderActivity.java | 353 +++++----- .../src/main/res/layout/crypto_provider_demo.xml | 6 +- .../src/main/res/layout/intent_demo.xml | 4 +- .../org/openintents/openpgp/IOpenPgpCallback.aidl | 45 -- .../openpgp/IOpenPgpKeyIdsCallback.aidl | 39 -- .../org/openintents/openpgp/IOpenPgpService.aidl | 9 +- .../aidl/org/openintents/openpgp/OpenPgpData.aidl | 20 - .../java/org/openintents/openpgp/OpenPgpData.java | 127 ---- .../openpgp/OpenPgpSignatureResult.java | 8 +- .../openintents/openpgp/util/OpenPgpConstants.java | 1 + OpenPGP-Keychain/src/main/AndroidManifest.xml | 26 +- .../service/exception/NoUserIdsException.java | 10 - .../UserInteractionRequiredException.java | 10 - .../exception/WrongPackageSignatureException.java | 10 - .../exception/WrongPassphraseException.java | 10 - .../keychain/service/remote/OpenPgpService.java | 715 +++++++-------------- .../keychain/service/remote/RemoteService.java | 1 - .../service/remote/RemoteServiceActivity.java | 77 +-- .../remote/WrongPackageSignatureException.java | 10 + .../org/openintents/openpgp/IOpenPgpCallback.aidl | 45 -- .../openpgp/IOpenPgpKeyIdsCallback.aidl | 39 -- .../org/openintents/openpgp/IOpenPgpService.aidl | 9 +- .../aidl/org/openintents/openpgp/OpenPgpData.aidl | 20 - .../java/org/openintents/openpgp/OpenPgpData.java | 127 ---- .../openpgp/OpenPgpSignatureResult.java | 8 +- .../openintents/openpgp/util/OpenPgpConstants.java | 1 + 26 files changed, 493 insertions(+), 1237 deletions(-) delete mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl delete mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl delete mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl delete mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java create mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java delete mode 100644 libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl delete mode 100644 libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl delete mode 100644 libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl delete mode 100644 libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java diff --git a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java index 39843eb82..a7060abb2 100644 --- a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java +++ b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java @@ -25,11 +25,11 @@ import android.content.IntentSender; import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.support.v4.app.TaskStackBuilder; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; +import android.widget.Button; import android.widget.EditText; import android.widget.ListAdapter; import android.widget.TextView; @@ -54,13 +54,17 @@ public class OpenPgpProviderActivity extends Activity { EditText mMessage; EditText mCiphertext; EditText mEncryptUserIds; + Button mSign; + Button mEncrypt; + Button mSignAndEncrypt; + Button mDecryptAndVerify; private OpenPgpServiceConnection mCryptoServiceConnection; public static final int REQUEST_CODE_SIGN = 9910; public static final int REQUEST_CODE_ENCRYPT = 9911; - public static final int REQUEST_CODE_SIGN_AND_ENC = 9912; - public static final int REQUEST_CODE_DECRYPT = 9913; + public static final int REQUEST_CODE_SIGN_AND_ENCRYPT = 9912; + public static final int REQUEST_CODE_DECRYPT_AND_VERIFY = 9913; @Override public void onCreate(Bundle icicle) { @@ -73,127 +77,38 @@ public class OpenPgpProviderActivity extends Activity { mCiphertext = (EditText) findViewById(R.id.crypto_provider_demo_ciphertext); mEncryptUserIds = (EditText) findViewById(R.id.crypto_provider_demo_encrypt_user_id); + mSign = (Button) findViewById(R.id.crypto_provider_demo_sign); + mEncrypt = (Button) findViewById(R.id.crypto_provider_demo_encrypt); + mSignAndEncrypt = (Button) findViewById(R.id.crypto_provider_demo_sign_and_encrypt); + mDecryptAndVerify = (Button) findViewById(R.id.crypto_provider_demo_decrypt_and_verify); + mSign.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + sign(new Bundle()); + } + }); + mEncrypt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + encrypt(new Bundle()); + } + }); + mSignAndEncrypt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + signAndEncrypt(new Bundle()); + } + }); + mDecryptAndVerify.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + decryptAndVerify(new Bundle()); + } + }); + selectCryptoProvider(); } -// /** -// * Callback from remote openpgp service -// */ -// final IOpenPgpKeyIdsCallback.Stub getKeysEncryptCallback = new IOpenPgpKeyIdsCallback.Stub() { -// -// @Override -// public void onSuccess(final long[] keyIds) throws RemoteException { -// Log.d(Constants.TAG, "getKeysEncryptCallback keyId " + keyIds[0]); -// mActivity.runOnUiThread(new Runnable() { -// -// @Override -// public void run() { -// // encrypt after getting key ids -// String inputStr = mMessage.getText().toString(); -// OpenPgpData input = new OpenPgpData(inputStr); -// -// Log.d(Constants.TAG, "getKeysEncryptCallback inputStr " + inputStr); -// -// try { -// mCryptoServiceConnection.getService().encrypt(input, -// new OpenPgpData(OpenPgpData.TYPE_STRING), keyIds, encryptCallback); -// } catch (RemoteException e) { -// Log.e(Constants.TAG, "CryptoProviderDemo", e); -// } -// } -// }); -// } -// -// @Override -// public void onError(OpenPgpError error) throws RemoteException { -// handleError(error); -// } -// -// }; -// -// final IOpenPgpKeyIdsCallback.Stub getKeysSignAndEncryptCallback = new IOpenPgpKeyIdsCallback.Stub() { -// -// @Override -// public void onSuccess(final long[] keyIds) throws RemoteException { -// Log.d(Constants.TAG, "getKeysSignAndEncryptCallback keyId " + keyIds[0]); -// -// mActivity.runOnUiThread(new Runnable() { -// -// @Override -// public void run() { -// // encrypt after getting key ids -// String inputStr = mMessage.getText().toString(); -// OpenPgpData input = new OpenPgpData(inputStr); -// -// try { -// mCryptoServiceConnection.getService().signAndEncrypt(input, -// new OpenPgpData(OpenPgpData.TYPE_STRING), keyIds, encryptCallback); -// } catch (RemoteException e) { -// Log.e(Constants.TAG, "CryptoProviderDemo", e); -// } -// } -// }); -// } -// -// @Override -// public void onError(OpenPgpError error) throws RemoteException { -// handleError(error); -// } -// -// }; -// -// final IOpenPgpCallback.Stub encryptCallback = new IOpenPgpCallback.Stub() { -// -// @Override -// public void onSuccess(final OpenPgpData output, OpenPgpSignatureResult signatureResult) -// throws RemoteException { -// Log.d(Constants.TAG, "encryptCallback"); -// -// runOnUiThread(new Runnable() { -// -// @Override -// public void run() { -// mCiphertext.setText(output.getString()); -// } -// }); -// } -// -// @Override -// public void onError(OpenPgpError error) throws RemoteException { -// handleError(error); -// } -// -// }; -// -// final IOpenPgpCallback.Stub decryptAndVerifyCallback = new IOpenPgpCallback.Stub() { -// -// @Override -// public void onSuccess(final OpenPgpData output, final OpenPgpSignatureResult signatureResult) -// throws RemoteException { -// Log.d(Constants.TAG, "decryptAndVerifyCallback"); -// -// runOnUiThread(new Runnable() { -// -// @Override -// public void run() { -// mMessage.setText(output.getString()); -// if (signatureResult != null) { -// Toast.makeText(OpenPgpProviderActivity.this, -// "signature result:\n" + signatureResult.toString(), -// Toast.LENGTH_LONG).show(); -// } -// } -// }); -// -// } -// -// @Override -// public void onError(OpenPgpError error) throws RemoteException { -// handleError(error); -// } -// -// }; - private void handleError(final OpenPgpError error) { mActivity.runOnUiThread(new Runnable() { @@ -208,28 +123,30 @@ public class OpenPgpProviderActivity extends Activity { }); } - public void encryptOnClick(View view) { -// try { -// mCryptoServiceConnection.getService().getKeyIds( -// mEncryptUserIds.getText().toString().split(","), true, getKeysEncryptCallback); -// } catch (RemoteException e) { -// Log.e(Constants.TAG, "CryptoProviderDemo", e); -// } - } - - public void signOnClick(View view) { + private InputStream getInputstream(boolean ciphertext) { InputStream is = null; try { - String inputStr = mMessage.getText().toString(); + String inputStr = null; + if (ciphertext) { + inputStr = mCiphertext.getText().toString(); + } else { + inputStr = mMessage.getText().toString(); + } is = new ByteArrayInputStream(inputStr.getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { e.printStackTrace(); } + + return is; + } + + + public void sign(Bundle params) { + InputStream is = getInputstream(false); final ByteArrayOutputStream os = new ByteArrayOutputStream(); OpenPgpApi api = new OpenPgpApi(mCryptoServiceConnection.getService()); - api.sign(new Bundle(), is, os, new OpenPgpApi.IOpenPgpCallback() { + api.sign(params, is, os, new OpenPgpApi.IOpenPgpCallback() { @Override public void onReturn(Bundle result) { switch (result.getInt(OpenPgpConstants.RESULT_CODE)) { @@ -248,52 +165,128 @@ public class OpenPgpProviderActivity extends Activity { PendingIntent pi = result.getParcelable(OpenPgpConstants.RESULT_INTENT); try { OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(), - REQUEST_CODE_SIGN, null, // or new Intent() (in billing) + REQUEST_CODE_SIGN, null, 0, 0, 0); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); } -// try { -// pi.send(OpenPgpProviderActivity.this, 42, null, new PendingIntent.OnFinished() { -// -// @Override -// public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras) { -// Log.d(Constants.TAG, "onSendFinished"); -// Log.d(Constants.TAG, "resultCode: " + resultCode); -// -// } -// }, null); -// } catch (PendingIntent.CanceledException e) { -// e.printStackTrace(); -// } break; } } } }); + } + + public void encrypt(Bundle params) { + params.putStringArray(OpenPgpConstants.PARAMS_USER_IDS, mEncryptUserIds.getText().toString().split(",")); + + InputStream is = getInputstream(false); + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + OpenPgpApi api = new OpenPgpApi(mCryptoServiceConnection.getService()); + api.encrypt(params, is, os, new OpenPgpApi.IOpenPgpCallback() { + @Override + public void onReturn(Bundle result) { + switch (result.getInt(OpenPgpConstants.RESULT_CODE)) { + case OpenPgpConstants.RESULT_CODE_SUCCESS: { + try { + Log.d(OpenPgpConstants.TAG, "result: " + os.toByteArray().length + + " str=" + os.toString("UTF-8")); + + mCiphertext.setText(os.toString("UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + break; + } + case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED: { + PendingIntent pi = result.getParcelable(OpenPgpConstants.RESULT_INTENT); + try { + OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(), + REQUEST_CODE_ENCRYPT, null, + 0, 0, 0); + } catch (IntentSender.SendIntentException e) { + e.printStackTrace(); + } + break; + } + } + } + }); } - public void signAndEncryptOnClick(View view) { -// try { -// mCryptoServiceConnection.getService().getKeyIds( -// mEncryptUserIds.getText().toString().split(","), true, -// getKeysSignAndEncryptCallback); -// } catch (RemoteException e) { -// Log.e(Constants.TAG, "CryptoProviderDemo", e); -// } + public void signAndEncrypt(Bundle params) { + params.putStringArray(OpenPgpConstants.PARAMS_USER_IDS, mEncryptUserIds.getText().toString().split(",")); + + InputStream is = getInputstream(false); + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + + OpenPgpApi api = new OpenPgpApi(mCryptoServiceConnection.getService()); + api.signAndEncrypt(params, is, os, new OpenPgpApi.IOpenPgpCallback() { + @Override + public void onReturn(Bundle result) { + switch (result.getInt(OpenPgpConstants.RESULT_CODE)) { + case OpenPgpConstants.RESULT_CODE_SUCCESS: { + try { + Log.d(OpenPgpConstants.TAG, "result: " + os.toByteArray().length + + " str=" + os.toString("UTF-8")); + + mCiphertext.setText(os.toString("UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + break; + } + case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED: { + PendingIntent pi = result.getParcelable(OpenPgpConstants.RESULT_INTENT); + try { + OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(), + REQUEST_CODE_SIGN_AND_ENCRYPT, null, + 0, 0, 0); + } catch (IntentSender.SendIntentException e) { + e.printStackTrace(); + } + break; + } + } + } + }); } - public void decryptAndVerifyOnClick(View view) { -// String inputStr = mCiphertext.getText().toString(); -// OpenPgpData input = new OpenPgpData(inputStr); -// -// try { -// mCryptoServiceConnection.getService().decryptAndVerify(input, -// new OpenPgpData(OpenPgpData.TYPE_STRING), decryptAndVerifyCallback); -// } catch (RemoteException e) { -// Log.e(Constants.TAG, "CryptoProviderDemo", e); -// } + public void decryptAndVerify(Bundle params) { + InputStream is = getInputstream(true); + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + + OpenPgpApi api = new OpenPgpApi(mCryptoServiceConnection.getService()); + api.decryptAndVerify(params, is, os, new OpenPgpApi.IOpenPgpCallback() { + @Override + public void onReturn(Bundle result) { + switch (result.getInt(OpenPgpConstants.RESULT_CODE)) { + case OpenPgpConstants.RESULT_CODE_SUCCESS: { + try { + Log.d(OpenPgpConstants.TAG, "result: " + os.toByteArray().length + + " str=" + os.toString("UTF-8")); + + mCiphertext.setText(os.toString("UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + break; + } + case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED: { + PendingIntent pi = result.getParcelable(OpenPgpConstants.RESULT_INTENT); + try { + OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(), + REQUEST_CODE_DECRYPT_AND_VERIFY, null, + 0, 0, 0); + } catch (IntentSender.SendIntentException e) { + e.printStackTrace(); + } + break; + } + } + } + }); } @Override @@ -304,8 +297,34 @@ public class OpenPgpProviderActivity extends Activity { case REQUEST_CODE_SIGN: { Log.d(Constants.TAG, "resultCode: " + resultCode); + // try to sign again after password caching + if (resultCode == RESULT_OK) { + sign(new Bundle()); + } + } + case REQUEST_CODE_ENCRYPT: { + Log.d(Constants.TAG, "resultCode: " + resultCode); + + // try to sign again after password caching + if (resultCode == RESULT_OK) { + // use data extras now as params for call (they now include key ids! + encrypt(data.getExtras()); + } + } + case REQUEST_CODE_SIGN_AND_ENCRYPT: { + Log.d(Constants.TAG, "resultCode: " + resultCode); + + // try to sign again after password caching + if (resultCode == RESULT_OK) { + signAndEncrypt(data.getExtras()); + } + } + case REQUEST_CODE_DECRYPT_AND_VERIFY: { + Log.d(Constants.TAG, "resultCode: " + resultCode); + + // try to sign again after password caching if (resultCode == RESULT_OK) { - signOnClick(null); + decryptAndVerify(new Bundle()); } } } diff --git a/OpenPGP-Keychain-API/example-app/src/main/res/layout/crypto_provider_demo.xml b/OpenPGP-Keychain-API/example-app/src/main/res/layout/crypto_provider_demo.xml index 9f2a0e6ee..6647a417b 100644 --- a/OpenPGP-Keychain-API/example-app/src/main/res/layout/crypto_provider_demo.xml +++ b/OpenPGP-Keychain-API/example-app/src/main/res/layout/crypto_provider_demo.xml @@ -54,7 +54,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" - android:onClick="encryptOnClick" android:text="Encrypt" />