aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2014-02-17 20:03:38 +0100
committerDominik Schürmann <dominik@dominikschuermann.de>2014-02-17 20:03:38 +0100
commit2e3d0d444180ef7217e6e960d2092e4f3de4c198 (patch)
tree778dc901f287fff9aeb1c9d3d41d7053eeccf1b0
parent7b819e65de71a17827a3264a1a8663ca0d30b48c (diff)
parentd3181f4478ce29fc96d101f5f72b4e82c03ec5e0 (diff)
downloadopen-keychain-2e3d0d444180ef7217e6e960d2092e4f3de4c198.tar.gz
open-keychain-2e3d0d444180ef7217e6e960d2092e4f3de4c198.tar.bz2
open-keychain-2e3d0d444180ef7217e6e960d2092e4f3de4c198.zip
Merge pull request #277 from openpgp-keychain/new-api
New api
-rw-r--r--OpenPGP-Keychain-API/example-app/build.gradle5
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/AndroidManifest.xml13
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/AidlDemoActivity2.java168
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/BaseActivity.java30
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/IntentActivity.java584
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java453
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/res/layout/aidl_demo2.xml40
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/res/layout/crypto_provider_demo.xml83
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/res/layout/intent.xml (renamed from OpenPGP-Keychain-API/example-app/src/main/res/layout/intent_demo.xml)4
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/res/layout/openpgp_provider.xml108
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/res/xml/base_preference.xml15
-rw-r--r--OpenPGP-Keychain-API/example-app/src/main/res/xml/intent_preference.xml30
-rw-r--r--OpenPGP-Keychain-API/gradle/wrapper/gradle-wrapper.properties4
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/AndroidManifest.xml (renamed from OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/AndroidManifest.xml)2
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/build.gradle16
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-hdpi/ic_action_cancel_launchersize.pngbin0 -> 1520 bytes
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-mdpi/ic_action_cancel_launchersize.pngbin0 -> 1032 bytes
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-xhdpi/ic_action_cancel_launchersize.pngbin0 -> 1570 bytes
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-xxhdpi/ic_action_cancel_launchersize.pngbin0 -> 2345 bytes
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/res/values/strings.xml6
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl45
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl39
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl143
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl20
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl20
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl20
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java10
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java127
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java52
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/IOpenPgpService.aidl85
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpError.java (renamed from libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java)11
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpSignatureResult.java (renamed from OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java)10
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpApi.java198
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpConstants.java53
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpListPreference.java (renamed from OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java)100
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpServiceConnection.java (renamed from OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java)9
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpUtils.java64
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java104
-rw-r--r--OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/sufficientlysecure/keychain/api/OpenKeychainIntents.java37
-rw-r--r--OpenPGP-Keychain/build.gradle2
-rw-r--r--OpenPGP-Keychain/src/main/AndroidManifest.xml66
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java10
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java10
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java10
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java798
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java217
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java172
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java)2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java1
-rw-r--r--OpenPGP-Keychain/src/main/res/values/strings.xml4
-rw-r--r--README.md43
-rw-r--r--Resources/old extended service/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl (renamed from OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl)0
-rw-r--r--Resources/old extended service/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl (renamed from OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl)0
-rw-r--r--Resources/old extended service/src/main/java/ExtendedApiService.java (renamed from OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java)0
-rw-r--r--build.gradle2
-rw-r--r--libraries/keychain-api-library/AndroidManifest.xml (renamed from libraries/keychain-api-library/src/main/AndroidManifest.xml)2
-rw-r--r--libraries/keychain-api-library/build.gradle25
-rw-r--r--libraries/keychain-api-library/res/drawable-hdpi/ic_action_cancel_launchersize.pngbin0 -> 1520 bytes
-rw-r--r--libraries/keychain-api-library/res/drawable-mdpi/ic_action_cancel_launchersize.pngbin0 -> 1032 bytes
-rw-r--r--libraries/keychain-api-library/res/drawable-xhdpi/ic_action_cancel_launchersize.pngbin0 -> 1570 bytes
-rw-r--r--libraries/keychain-api-library/res/drawable-xxhdpi/ic_action_cancel_launchersize.pngbin0 -> 2345 bytes
-rw-r--r--libraries/keychain-api-library/res/values/strings.xml6
-rw-r--r--libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl45
-rw-r--r--libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl39
-rw-r--r--libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl143
-rw-r--r--libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl20
-rw-r--r--libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl20
-rw-r--r--libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl20
-rw-r--r--libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl24
-rw-r--r--libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl48
-rw-r--r--libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java10
-rw-r--r--libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java127
-rw-r--r--libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java52
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/IOpenPgpService.aidl85
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpError.java (renamed from OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java)11
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpSignatureResult.java (renamed from libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java)10
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpApi.java198
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpConstants.java54
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpListPreference.java (renamed from libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java)100
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpServiceConnection.java (renamed from libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java)9
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpUtils.java64
-rw-r--r--libraries/keychain-api-library/src/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java104
-rw-r--r--libraries/keychain-api-library/src/org/sufficientlysecure/keychain/api/OpenKeychainIntents.java37
86 files changed, 2733 insertions, 2571 deletions
diff --git a/OpenPGP-Keychain-API/example-app/build.gradle b/OpenPGP-Keychain-API/example-app/build.gradle
index 99a09f094..1f8854431 100644
--- a/OpenPGP-Keychain-API/example-app/build.gradle
+++ b/OpenPGP-Keychain-API/example-app/build.gradle
@@ -1,10 +1,11 @@
+// please leave this here, so this library builds on its own
buildscript {
repositories {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.8.0'
+ classpath 'com.android.tools.build:gradle:0.8.3'
}
}
@@ -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..42465cef8 100644
--- a/OpenPGP-Keychain-API/example-app/src/main/AndroidManifest.xml
+++ b/OpenPGP-Keychain-API/example-app/src/main/AndroidManifest.xml
@@ -2,19 +2,19 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sufficientlysecure.keychain.demo"
android:versionCode="2"
- android:versionName="1.1" >
+ android:versionName="1.1">
<uses-sdk
- android:minSdkVersion="8"
+ android:minSdkVersion="9"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
- android:label="OpenPGP Keychain API Demo" >
+ android:label="OpenPGP Keychain API Demo">
<activity
android:name=".BaseActivity"
- android:label="OpenPGP Keychain API Demo" >
+ android:label="OpenPGP Keychain API Demo">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -26,9 +26,8 @@
android:label="OpenPGP Provider"
android:windowSoftInputMode="stateHidden" />
<activity
- android:name=".AidlDemoActivity2"
- android:label="Aidl Demo (ACCESS_KEYS permission)"
- android:windowSoftInputMode="stateHidden" />
+ android:name=".IntentActivity"
+ android:label="Intents" />
</application>
</manifest> \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/AidlDemoActivity2.java b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/AidlDemoActivity2.java
deleted file mode 100644
index b6e211955..000000000
--- a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/AidlDemoActivity2.java
+++ /dev/null
@@ -1,168 +0,0 @@
-///*
-// * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
-// *
-// * 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.sufficientlysecure.keychain.demo;
-//
-//import java.util.ArrayList;
-//import java.util.List;
-//
-//import org.sufficientlysecure.keychain.demo.R;
-//import org.sufficientlysecure.keychain.integration.KeychainData;
-//import org.sufficientlysecure.keychain.integration.KeychainIntentHelper;
-//import org.sufficientlysecure.keychain.service.IKeychainKeyService;
-//import org.sufficientlysecure.keychain.service.handler.IKeychainGetKeyringsHandler;
-//
-//import android.annotation.SuppressLint;
-//import android.app.Activity;
-//import android.app.AlertDialog;
-//import android.content.ComponentName;
-//import android.content.Context;
-//import android.content.Intent;
-//import android.content.ServiceConnection;
-//import android.os.Bundle;
-//import android.os.IBinder;
-//import android.os.RemoteException;
-//import android.util.Base64;
-//import android.view.View;
-//import android.widget.TextView;
-//
-//public class AidlDemoActivity2 extends Activity {
-// Activity mActivity;
-//
-// TextView mKeyringsTextView;
-//
-// KeychainIntentHelper mKeychainIntentHelper;
-// KeychainData mKeychainData;
-//
-// byte[] keysBytes;
-// ArrayList<String> keysStrings;
-//
-// private IKeychainKeyService service = null;
-// private ServiceConnection svcConn = new ServiceConnection() {
-// public void onServiceConnected(ComponentName className, IBinder binder) {
-// service = IKeychainKeyService.Stub.asInterface(binder);
-// }
-//
-// public void onServiceDisconnected(ComponentName className) {
-// service = null;
-// }
-// };
-//
-// @Override
-// public void onCreate(Bundle icicle) {
-// super.onCreate(icicle);
-// setContentView(R.layout.aidl_demo2);
-//
-// mActivity = this;
-//
-// mKeyringsTextView = (TextView) findViewById(R.id.aidl_demo_keyrings);
-//
-// mKeychainIntentHelper = new KeychainIntentHelper(mActivity);
-// mKeychainData = new KeychainData();
-//
-// bindService(new Intent(IKeychainKeyService.class.getName()), svcConn,
-// Context.BIND_AUTO_CREATE);
-// }
-//
-// public void getKeyringsStringsOnClick(View view) {
-// try {
-// service.getPublicKeyRings(mKeychainData.getPublicKeys(), true, getKeyringsHandler);
-// } catch (RemoteException e) {
-// exceptionImplementation(-1, e.toString());
-// }
-// }
-//
-// public void getKeyringsBytesOnClick(View view) {
-// try {
-// service.getPublicKeyRings(mKeychainData.getPublicKeys(), false, getKeyringsHandler);
-// } catch (RemoteException e) {
-// exceptionImplementation(-1, e.toString());
-// }
-// }
-//
-// @SuppressLint("NewApi")
-// private void updateView() {
-// if (keysBytes != null) {
-// mKeyringsTextView.setText(Base64.encodeToString(keysBytes, Base64.DEFAULT));
-// } else if (keysStrings != null) {
-// mKeyringsTextView.setText("");
-// for (String output : keysStrings) {
-// mKeyringsTextView.append(output);
-// }
-// }
-// }
-//
-// @Override
-// public void onDestroy() {
-// super.onDestroy();
-//
-// unbindService(svcConn);
-// }
-//
-// private void exceptionImplementation(int exceptionId, String error) {
-// AlertDialog.Builder builder = new AlertDialog.Builder(this);
-// builder.setTitle("Exception!").setMessage(error).setPositiveButton("OK", null).show();
-// }
-//
-// private final IKeychainGetKeyringsHandler.Stub getKeyringsHandler = new IKeychainGetKeyringsHandler.Stub() {
-//
-// @Override
-// public void onException(final int exceptionId, final String message) throws RemoteException {
-// runOnUiThread(new Runnable() {
-// public void run() {
-// exceptionImplementation(exceptionId, message);
-// }
-// });
-// }
-//
-// @Override
-// public void onSuccess(final byte[] outputBytes, final List<String> outputStrings)
-// throws RemoteException {
-// runOnUiThread(new Runnable() {
-// public void run() {
-// if (outputBytes != null) {
-// keysBytes = outputBytes;
-// keysStrings = null;
-// } else if (outputStrings != null) {
-// keysBytes = null;
-// keysStrings = (ArrayList<String>) outputStrings;
-// }
-// updateView();
-// }
-// });
-//
-// }
-//
-// };
-//
-// public void selectEncryptionKeysOnClick(View view) {
-// mKeychainIntentHelper.selectPublicKeys("user@example.com");
-// }
-//
-// @Override
-// protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-// // this updates the mKeychainData object to the result of the methods
-// boolean result = mKeychainIntentHelper.onActivityResult(requestCode, resultCode, data,
-// mKeychainData);
-// if (result) {
-// updateView();
-// }
-//
-// // continue with other activity results
-// super.onActivityResult(requestCode, resultCode, data);
-// }
-//
-//}
diff --git a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/BaseActivity.java b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/BaseActivity.java
index 5b286f208..dd642d879 100644
--- a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/BaseActivity.java
+++ b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/BaseActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,6 @@
package org.sufficientlysecure.keychain.demo;
-import org.sufficientlysecure.keychain.demo.R;
-
-import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.preference.Preference;
@@ -27,13 +24,8 @@ import android.preference.PreferenceActivity;
import android.widget.Toast;
public class BaseActivity extends PreferenceActivity {
- private Activity mActivity;
-
private Preference mIntentDemo;
- private Preference mContentProviderDemo;
private Preference mCryptoProvider;
- private Preference mAidlDemo;
- private Preference mAidlDemo2;
/**
* Called when the activity is first created.
@@ -42,23 +34,17 @@ public class BaseActivity extends PreferenceActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mActivity = this;
-
// load preferences from xml
addPreferencesFromResource(R.xml.base_preference);
// find preferences
mIntentDemo = (Preference) findPreference("intent_demo");
- mContentProviderDemo = (Preference) findPreference("content_provider_demo");
mCryptoProvider = (Preference) findPreference("openpgp_provider_demo");
- mAidlDemo = (Preference) findPreference("aidl_demo");
- mAidlDemo2 = (Preference) findPreference("aidl_demo2");
mIntentDemo.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- // startActivity(new Intent(mActivity, IntentDemoActivity.class));
- Toast.makeText(BaseActivity.this, "Not implemented!", Toast.LENGTH_LONG).show();
+ startActivity(new Intent(BaseActivity.this, IntentActivity.class));
return false;
}
@@ -67,21 +53,11 @@ public class BaseActivity extends PreferenceActivity {
mCryptoProvider.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- startActivity(new Intent(mActivity, OpenPgpProviderActivity.class));
+ startActivity(new Intent(BaseActivity.this, OpenPgpProviderActivity.class));
return false;
}
});
-
- // mAidlDemo2.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- // @Override
- // public boolean onPreferenceClick(Preference preference) {
- // startActivity(new Intent(mActivity, AidlDemoActivity2.class));
- //
- // return false;
- // }
- // });
-
}
}
diff --git a/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/IntentActivity.java b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/IntentActivity.java
new file mode 100644
index 000000000..ad1b55df0
--- /dev/null
+++ b/OpenPGP-Keychain-API/example-app/src/main/java/org/sufficientlysecure/keychain/demo/IntentActivity.java
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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.sufficientlysecure.keychain.demo;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceActivity;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.widget.Toast;
+
+import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
+
+import java.io.UnsupportedEncodingException;
+
+public class IntentActivity extends PreferenceActivity {
+
+ private static final int SELECT_PHOTO = 100;
+
+ /**
+ * Called when the activity is first created.
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // load preferences from xml
+ addPreferencesFromResource(R.xml.intent_preference);
+
+ // find preferences
+ Preference encrypt = (Preference) findPreference("ENCRYPT");
+ Preference encryptUri = (Preference) findPreference("ENCRYPT_URI");
+ Preference decrypt = (Preference) findPreference("DECRYPT");
+ Preference import_key = (Preference) findPreference("IMPORT_KEY");
+ Preference import_key_from_keyserver = (Preference) findPreference("IMPORT_KEY_FROM_KEYSERVER");
+ Preference import_key_from_qr_code = (Preference) findPreference("IMPORT_KEY_FROM_QR_CODE");
+ Preference openpgp4fpr = (Preference) findPreference("openpgp4fpr");
+
+ // To prevent Android Studio from complaining...
+ assert encrypt != null;
+ assert encryptUri != null;
+ assert decrypt != null;
+ assert import_key != null;
+ assert import_key_from_keyserver != null;
+ assert import_key_from_qr_code != null;
+ assert openpgp4fpr != null;
+
+ encrypt.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ try {
+ Intent intent = new Intent(OpenKeychainIntents.ENCRYPT);
+ intent.putExtra(OpenKeychainIntents.ENCRYPT_EXTRA_TEXT, "Hello world!");
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(IntentActivity.this, "Activity not found!", Toast.LENGTH_LONG).show();
+ }
+
+ return false;
+ }
+ });
+
+ encryptUri.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
+ photoPickerIntent.setType("image/*");
+ startActivityForResult(photoPickerIntent, SELECT_PHOTO);
+
+ return false;
+ }
+ });
+
+ decrypt.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ try {
+ Intent intent = new Intent(OpenKeychainIntents.DECRYPT);
+ intent.putExtra(OpenKeychainIntents.DECRYPT_EXTRA_TEXT, TEST_SIGNED_MESSAGE);
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(IntentActivity.this, "Activity not found!", Toast.LENGTH_LONG).show();
+ }
+
+ return false;
+ }
+ });
+
+ import_key.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ try {
+ Intent intent = new Intent(OpenKeychainIntents.IMPORT_KEY);
+ byte[] pubkey = null;
+ try {
+ pubkey = TEST_PUBKEY.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ intent.putExtra(OpenKeychainIntents.IMPORT_KEY_EXTRA_KEY_BYTES, pubkey);
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(IntentActivity.this, "Activity not found!", Toast.LENGTH_LONG).show();
+ }
+
+ return false;
+ }
+ });
+
+ import_key_from_keyserver.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ try {
+ Intent intent = new Intent(OpenKeychainIntents.IMPORT_KEY_FROM_KEYSERVER);
+ intent.putExtra(OpenKeychainIntents.IMPORT_KEY_FROM_KEYSERVER_QUERY, "Richard Stallman");
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(IntentActivity.this, "Activity not found!", Toast.LENGTH_LONG).show();
+ }
+
+ return false;
+ }
+ });
+
+ import_key_from_qr_code.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ try {
+ Intent intent = new Intent(OpenKeychainIntents.IMPORT_KEY_FROM_QR_CODE);
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(IntentActivity.this, "Activity not found!", Toast.LENGTH_LONG).show();
+ }
+
+ return false;
+ }
+ });
+
+ openpgp4fpr.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ try {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("openpgp4fpr:73EE2314F65FA92EC2390D3A718C070100012282"));
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(IntentActivity.this, "Activity not found!", Toast.LENGTH_LONG).show();
+ }
+
+ return false;
+ }
+ });
+
+
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
+ super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
+
+ switch (requestCode) {
+ case SELECT_PHOTO:
+ if (resultCode == RESULT_OK) {
+ Uri selectedImage = imageReturnedIntent.getData();
+
+ String[] filePathColumn = {MediaStore.Images.Media.DATA};
+
+ Cursor cursor = getContentResolver().query(
+ selectedImage, filePathColumn, null, null, null);
+ cursor.moveToFirst();
+
+ int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
+ String filePath = cursor.getString(columnIndex);
+ cursor.close();
+
+ // TODO: after fixing DECRYPT, we could use Uri selectedImage directly
+ Log.d(Constants.TAG, "filePath: " + filePath);
+
+ try {
+ Intent intent = new Intent(OpenKeychainIntents.ENCRYPT);
+ Uri dataUri = Uri.parse("file://" + filePath);
+ Log.d(Constants.TAG, "Uri: " + dataUri);
+ intent.setData(dataUri);
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(IntentActivity.this, "Activity not found!", Toast.LENGTH_LONG).show();
+ }
+ }
+ }
+ }
+
+ private static final String TEST_SIGNED_MESSAGE = "-----BEGIN PGP SIGNED MESSAGE-----\n" +
+ "Hash: SHA1\n" +
+ "\n" +
+ "Hello world!\n" +
+ "-----BEGIN PGP SIGNATURE-----\n" +
+ "Version: GnuPG v1.4.12 (GNU/Linux)\n" +
+ "Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/\n" +
+ "\n" +
+ "iQEcBAEBAgAGBQJS/7vTAAoJEHGMBwEAASKCkGYH/2jBLzamVyqd61jrjMQM0jUv\n" +
+ "MkDcPUxPrYH3wZOO0HcgdBQEo66GZEC2ATmo8izJUMk35Q5jas99k0ac9pXhPUPE\n" +
+ "5qDXdQS10S07R6J0SeDYFWDSyrSiDTCZpFkVu3JGP/3S0SkMYXPzfYlh8Ciuxu7i\n" +
+ "FR5dmIiz3VQaBgTBSCBFEomNFM5ypynBJqKIzIty8v0NbV72Rtg6Xg76YqWQ/6MC\n" +
+ "/MlT3y3++HhfpEmLf5WLEXljbuZ4SfCybgYXG9gBzhJu3+gmBoSicdYTZDHSxBBR\n" +
+ "BwI+ueLbhgRz+gU+WJFE7xNw35xKtBp1C4PR0iKI8rZCSHLjsRVzor7iwDaR51M=\n" +
+ "=3Ydc\n" +
+ "-----END PGP SIGNATURE-----";
+
+ private static final String TEST_PUBKEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
+ "Version: GnuPG v1.4.12 (GNU/Linux)\n" +
+ "\n" +
+ "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\n" +
+ "k3wUxv46o0y15asU\n" +
+ "=Bbew\n" +
+ "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+}
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 4a96de5a1..d14703f2d 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
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,181 +16,103 @@
package org.sufficientlysecure.keychain.demo;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.openintents.openpgp.IOpenPgpKeyIdsCallback;
-import org.openintents.openpgp.OpenPgpData;
-import org.openintents.openpgp.OpenPgpError;
-import org.openintents.openpgp.OpenPgpServiceConnection;
-import org.openintents.openpgp.OpenPgpSignatureResult;
-import org.openintents.openpgp.IOpenPgpCallback;
-import org.openintents.openpgp.IOpenPgpService;
-
import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
+import android.app.PendingIntent;
import android.content.Intent;
-import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
+import android.content.IntentSender;
+import android.content.SharedPreferences;
import android.os.Bundle;
-import android.os.RemoteException;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
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;
import android.widget.Toast;
-public class OpenPgpProviderActivity extends Activity {
- Activity mActivity;
+import org.openintents.openpgp.OpenPgpError;
+import org.openintents.openpgp.util.OpenPgpApi;
+import org.openintents.openpgp.util.OpenPgpConstants;
+import org.openintents.openpgp.util.OpenPgpServiceConnection;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+public class OpenPgpProviderActivity extends Activity {
EditText mMessage;
EditText mCiphertext;
EditText mEncryptUserIds;
+ Button mSign;
+ Button mEncrypt;
+ Button mSignAndEncrypt;
+ Button mDecryptAndVerify;
+
+ OpenPgpServiceConnection mServiceConnection;
- 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_ENCRYPT = 9912;
+ public static final int REQUEST_CODE_DECRYPT_AND_VERIFY = 9913;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- setContentView(R.layout.crypto_provider_demo);
-
- mActivity = this;
+ setContentView(R.layout.openpgp_provider);
mMessage = (EditText) findViewById(R.id.crypto_provider_demo_message);
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);
- 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();
- }
- }
- });
-
- }
+ 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());
+ }
+ });
- @Override
- public void onError(OpenPgpError error) throws RemoteException {
- handleError(error);
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
+ String providerPackageName = settings.getString("openpgp_provider_list", "");
+ if (TextUtils.isEmpty(providerPackageName)) {
+ Toast.makeText(this, "No OpenPGP Provider selected!", Toast.LENGTH_LONG).show();
+ finish();
+ } else {
+ // bind to service
+ mServiceConnection = new OpenPgpServiceConnection(
+ OpenPgpProviderActivity.this, providerPackageName);
+ mServiceConnection.bindToService();
}
-
- };
+ }
private void handleError(final OpenPgpError error) {
- mActivity.runOnUiThread(new Runnable() {
+ runOnUiThread(new Runnable() {
@Override
public void run() {
- Toast.makeText(mActivity,
+ Toast.makeText(OpenPgpProviderActivity.this,
"onError id:" + error.getErrorId() + "\n\n" + error.getMessage(),
Toast.LENGTH_LONG).show();
Log.e(Constants.TAG, "onError getErrorId:" + error.getErrorId());
@@ -199,154 +121,157 @@ public class OpenPgpProviderActivity extends Activity {
});
}
- public void encryptOnClick(View view) {
+ /**
+ * Takes input from message or ciphertext EditText and turns it into a ByteArrayInputStream
+ *
+ * @param ciphertext
+ * @return
+ */
+ private InputStream getInputstream(boolean ciphertext) {
+ InputStream is = null;
try {
- mCryptoServiceConnection.getService().getKeyIds(
- mEncryptUserIds.getText().toString().split(","), true, getKeysEncryptCallback);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoProviderDemo", e);
+ 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 signOnClick(View view) {
- String inputStr = mMessage.getText().toString();
- OpenPgpData input = new OpenPgpData(inputStr);
+ private class MyCallback implements OpenPgpApi.IOpenPgpCallback {
+ boolean returnToCiphertextField;
+ ByteArrayOutputStream os;
+ int requestCode;
- try {
- mCryptoServiceConnection.getService().sign(input,
- new OpenPgpData(OpenPgpData.TYPE_STRING), encryptCallback);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoProviderDemo", e);
+ private MyCallback(boolean returnToCiphertextField, ByteArrayOutputStream os, int requestCode) {
+ this.returnToCiphertextField = returnToCiphertextField;
+ this.os = os;
+ this.requestCode = requestCode;
}
- }
- public void signAndEncryptOnClick(View view) {
- try {
- mCryptoServiceConnection.getService().getKeyIds(
- mEncryptUserIds.getText().toString().split(","), true,
- getKeysSignAndEncryptCallback);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoProviderDemo", e);
+ @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"));
+
+ if (returnToCiphertextField) {
+ mCiphertext.setText(os.toString("UTF-8"));
+ } else {
+ mMessage.setText(os.toString("UTF-8"));
+ }
+ } catch (UnsupportedEncodingException e) {
+ Log.e(Constants.TAG, "UnsupportedEncodingException", e);
+ }
+ break;
+ }
+ case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED: {
+ PendingIntent pi = result.getParcelable(OpenPgpConstants.RESULT_INTENT);
+ try {
+ OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(),
+ requestCode, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(Constants.TAG, "SendIntentException", e);
+ }
+ break;
+ }
+ case OpenPgpConstants.RESULT_CODE_ERROR: {
+ OpenPgpError error = result.getParcelable(OpenPgpConstants.RESULT_ERRORS);
+ handleError(error);
+ 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 sign(Bundle params) {
+ params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
- @Override
- public void onDestroy() {
- super.onDestroy();
+ InputStream is = getInputstream(false);
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
- if (mCryptoServiceConnection != null) {
- mCryptoServiceConnection.unbindFromService();
- }
+ OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
+ api.sign(params, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN));
}
- private static class OpenPgpProviderElement {
- private String packageName;
- private String simpleName;
- private Drawable icon;
+ public void encrypt(Bundle params) {
+ params.putStringArray(OpenPgpConstants.PARAMS_USER_IDS, mEncryptUserIds.getText().toString().split(","));
+ params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
- public OpenPgpProviderElement(String packageName, String simpleName, Drawable icon) {
- this.packageName = packageName;
- this.simpleName = simpleName;
- this.icon = icon;
- }
+ InputStream is = getInputstream(false);
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
- @Override
- public String toString() {
- return simpleName;
- }
+ OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
+ api.encrypt(params, is, os, new MyCallback(true, os, REQUEST_CODE_ENCRYPT));
}
- private void selectCryptoProvider() {
- Intent intent = new Intent(IOpenPgpService.class.getName());
+ public void signAndEncrypt(Bundle params) {
+ params.putStringArray(OpenPgpConstants.PARAMS_USER_IDS, mEncryptUserIds.getText().toString().split(","));
+ params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
- final ArrayList<OpenPgpProviderElement> providerList = new ArrayList<OpenPgpProviderElement>();
+ InputStream is = getInputstream(false);
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
- List<ResolveInfo> resInfo = getPackageManager().queryIntentServices(intent, 0);
- if (!resInfo.isEmpty()) {
- for (ResolveInfo resolveInfo : resInfo) {
- if (resolveInfo.serviceInfo == null)
- continue;
+ OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
+ api.signAndEncrypt(params, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN_AND_ENCRYPT));
+ }
- String packageName = resolveInfo.serviceInfo.packageName;
- String simpleName = String.valueOf(resolveInfo.serviceInfo
- .loadLabel(getPackageManager()));
- Drawable icon = resolveInfo.serviceInfo.loadIcon(getPackageManager());
- providerList.add(new OpenPgpProviderElement(packageName, simpleName, icon));
- }
- }
+ public void decryptAndVerify(Bundle params) {
+ params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
- AlertDialog.Builder alert = new AlertDialog.Builder(this);
- alert.setTitle("Select OpenPGP Provider!");
- alert.setCancelable(false);
+ InputStream is = getInputstream(true);
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
- if (!providerList.isEmpty()) {
- // add "disable OpenPGP provider"
- providerList.add(0, new OpenPgpProviderElement(null, "Disable OpenPGP Provider",
- getResources().getDrawable(android.R.drawable.ic_menu_close_clear_cancel)));
+ OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
+ api.decryptAndVerify(params, is, os, new MyCallback(false, os, REQUEST_CODE_DECRYPT_AND_VERIFY));
+ }
- // Init ArrayAdapter with OpenPGP Providers
- ListAdapter adapter = new ArrayAdapter<OpenPgpProviderElement>(this,
- android.R.layout.select_dialog_item, android.R.id.text1, providerList) {
- 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);
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
- // Put the image on the TextView
- tv.setCompoundDrawablesWithIntrinsicBounds(providerList.get(position).icon,
- null, null, null);
+ Log.d(Constants.TAG, "onActivityResult resultCode: " + resultCode);
- // Add margin between image and text (support various screen densities)
- int dp5 = (int) (5 * getResources().getDisplayMetrics().density + 0.5f);
- tv.setCompoundDrawablePadding(dp5);
+ // try again after user interaction
+ if (resultCode == RESULT_OK) {
+ Bundle params = data.getBundleExtra(OpenPgpConstants.PI_RESULT_PARAMS);
- return v;
+ switch (requestCode) {
+ case REQUEST_CODE_SIGN: {
+ sign(params);
+ break;
}
- };
-
- alert.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() {
-
- public void onClick(DialogInterface dialog, int position) {
- String packageName = providerList.get(position).packageName;
-
- if (packageName == null) {
- dialog.cancel();
- finish();
- }
-
- // bind to service
- mCryptoServiceConnection = new OpenPgpServiceConnection(
- OpenPgpProviderActivity.this, packageName);
- mCryptoServiceConnection.bindToService();
-
- dialog.dismiss();
+ case REQUEST_CODE_ENCRYPT: {
+ encrypt(params);
+ break;
}
- });
- } else {
- alert.setMessage("No OpenPGP Provider installed!");
+ case REQUEST_CODE_SIGN_AND_ENCRYPT: {
+ signAndEncrypt(params);
+ break;
+ }
+ case REQUEST_CODE_DECRYPT_AND_VERIFY: {
+ decryptAndVerify(params);
+ break;
+ }
+ }
}
+ }
- alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
-
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- finish();
- }
- });
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
- AlertDialog ad = alert.create();
- ad.show();
+ if (mServiceConnection != null) {
+ mServiceConnection.unbindFromService();
+ }
}
+
}
diff --git a/OpenPGP-Keychain-API/example-app/src/main/res/layout/aidl_demo2.xml b/OpenPGP-Keychain-API/example-app/src/main/res/layout/aidl_demo2.xml
deleted file mode 100644
index 73abd9b5c..000000000
--- a/OpenPGP-Keychain-API/example-app/src/main/res/layout/aidl_demo2.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
-
- <Button
- android:id="@+id/aidl_demo_select_encryption_key"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="selectEncryptionKeysOnClick"
- android:text="Select encryption key(s)" />
-
- <EditText
- android:id="@+id/aidl_demo_keyrings"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="keyrings output"
- android:textAppearance="@android:style/TextAppearance.Small" />
-
- <Button
- android:id="@+id/aidl_demo_get_keyrings_strings"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="getKeyringsStringsOnClick"
- android:text="getKeyrings as Strings" />
-
- <Button
- android:id="@+id/aidl_demo_get_keyrings_bytes"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="getKeyringsBytesOnClick"
- android:text="getKeyringsBytes" />
- </LinearLayout>
-
-</ScrollView> \ No newline at end of file
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
deleted file mode 100644
index 9f2a0e6ee..000000000
--- a/OpenPGP-Keychain-API/example-app/src/main/res/layout/crypto_provider_demo.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="Encrypt UserIds (split with &apos;,&apos;)"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <EditText
- android:id="@+id/crypto_provider_demo_encrypt_user_id"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="dominik@dominikschuermann.de"
- android:textAppearance="@android:style/TextAppearance.Small" />
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="Message"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <EditText
- android:id="@+id/crypto_provider_demo_message"
- android:layout_width="match_parent"
- android:layout_height="100dip"
- android:scrollHorizontally="true"
- android:scrollbars="vertical"
- android:text="message"
- android:textAppearance="@android:style/TextAppearance.Small" />
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="Ciphertext"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <EditText
- android:id="@+id/crypto_provider_demo_ciphertext"
- android:layout_width="match_parent"
- android:layout_height="100dip"
- android:text="ciphertext"
- android:textAppearance="@android:style/TextAppearance.Small" />
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
-
- <Button
- android:id="@+id/crypto_provider_demo_encrypt"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:onClick="encryptOnClick"
- android:text="Encrypt" />
-
- <Button
- android:id="@+id/crypto_provider_demo_sign"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:onClick="signOnClick"
- android:text="Sign" />
-
- <Button
- android:id="@+id/crypto_provider_demo_encrypt_and_sign"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:onClick="signAndEncryptOnClick"
- android:text="Sign and Encrypt" />
- </LinearLayout>
-
- <Button
- android:id="@+id/crypto_provider_demo_decrypt_and_verify"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="decryptAndVerifyOnClick"
- android:text="Decrypt and Verify" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/example-app/src/main/res/layout/intent_demo.xml b/OpenPGP-Keychain-API/example-app/src/main/res/layout/intent.xml
index a765343f9..ed416a05f 100644
--- a/OpenPGP-Keychain-API/example-app/src/main/res/layout/intent_demo.xml
+++ b/OpenPGP-Keychain-API/example-app/src/main/res/layout/intent.xml
@@ -12,7 +12,7 @@
android:id="@+id/Button02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:onClick="encryptOnClick"
+ android:onClick="encrypt"
android:text="Encrypt" />
<Button
@@ -54,7 +54,7 @@
android:id="@+id/intent_demo_encrypt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:onClick="encryptOnClick"
+ android:onClick="encrypt"
android:text="Encrypt" />
<Button
diff --git a/OpenPGP-Keychain-API/example-app/src/main/res/layout/openpgp_provider.xml b/OpenPGP-Keychain-API/example-app/src/main/res/layout/openpgp_provider.xml
new file mode 100644
index 000000000..6c2ce1a7c
--- /dev/null
+++ b/OpenPGP-Keychain-API/example-app/src/main/res/layout/openpgp_provider.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/parent_scroll"
+ android:fillViewport="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:padding="8dp"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Encrypt UserIds (split with &apos;,&apos;)"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+
+ <EditText
+ android:id="@+id/crypto_provider_demo_encrypt_user_id"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="dominik@dominikschuermann.de"
+ android:textAppearance="@android:style/TextAppearance.Small" />
+
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Message"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+
+ <ScrollView
+ android:id="@+id/child_scroll1"
+ android:fillViewport="true"
+ android:layout_width="match_parent"
+ android:layout_height="120dp">
+
+ <EditText
+ android:id="@+id/crypto_provider_demo_message"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollHorizontally="true"
+ android:scrollbars="vertical"
+ android:text="message"
+ android:textAppearance="@android:style/TextAppearance.Small" />
+ </ScrollView>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Ciphertext"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <ScrollView
+ android:id="@+id/child_scroll2"
+ android:fillViewport="true"
+ android:layout_width="match_parent"
+ android:layout_height="120dp">
+
+ <EditText
+ android:id="@+id/crypto_provider_demo_ciphertext"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="ciphertext"
+ android:textAppearance="@android:style/TextAppearance.Small" />
+ </ScrollView>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/crypto_provider_demo_sign"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Sign"
+ android:layout_gravity="center_vertical" />
+
+ <Button
+ android:id="@+id/crypto_provider_demo_encrypt"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Encrypt"
+ android:layout_gravity="center_vertical" />
+
+ <Button
+ android:id="@+id/crypto_provider_demo_sign_and_encrypt"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Sign and Encrypt"
+ android:layout_gravity="center_vertical" />
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/crypto_provider_demo_decrypt_and_verify"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Decrypt and Verify" />
+
+ </LinearLayout>
+</ScrollView> \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/example-app/src/main/res/xml/base_preference.xml b/OpenPGP-Keychain-API/example-app/src/main/res/xml/base_preference.xml
index 5febfad44..b38e07a36 100644
--- a/OpenPGP-Keychain-API/example-app/src/main/res/xml/base_preference.xml
+++ b/OpenPGP-Keychain-API/example-app/src/main/res/xml/base_preference.xml
@@ -1,23 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
- <PreferenceCategory android:title="Intent" >
+ <PreferenceCategory android:title="OpenKeychain Intents">
<Preference
android:key="intent_demo"
android:title="Intent Demo" />
</PreferenceCategory>
- <!-- <PreferenceCategory android:title="AIDL" > -->
- <!-- <Preference -->
- <!-- android:key="aidl_demo2" -->
- <!-- android:title="AIDL Demo (ACCESS_KEYS permission)" /> -->
- <!-- </PreferenceCategory> -->
- <PreferenceCategory android:title="OpenPGP Provider" >
- <org.openintents.openpgp.OpenPgpListPreference
+ <PreferenceCategory android:title="OpenPGP Provider API">
+ <org.openintents.openpgp.util.OpenPgpListPreference
android:key="openpgp_provider_list"
android:title="Select OpenPGP Provider!" />
<Preference
android:key="openpgp_provider_demo"
- android:title="OpenPGP Provider" />
+ android:title="OpenPGP Provider Demo" />
</PreferenceCategory>
</PreferenceScreen> \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/example-app/src/main/res/xml/intent_preference.xml b/OpenPGP-Keychain-API/example-app/src/main/res/xml/intent_preference.xml
new file mode 100644
index 000000000..801e4a78a
--- /dev/null
+++ b/OpenPGP-Keychain-API/example-app/src/main/res/xml/intent_preference.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceCategory android:title="Intents (org.sufficientlysecure.keychain.action.)">
+ <Preference
+ android:key="ENCRYPT"
+ android:title="ENCRYPT" />
+ <Preference
+ android:key="ENCRYPT_URI"
+ android:title="ENCRYPT with Uri" />
+ <Preference
+ android:key="DECRYPT"
+ android:title="DECRYPT" />
+ <Preference
+ android:key="IMPORT_KEY"
+ android:title="IMPORT_KEY" />
+ <Preference
+ android:key="IMPORT_KEY_FROM_KEYSERVER"
+ android:title="IMPORT_KEY_FROM_KEYSERVER" />
+ <Preference
+ android:key="IMPORT_KEY_FROM_QR_CODE"
+ android:title="IMPORT_KEY_FROM_QR_CODE" />
+ </PreferenceCategory>
+ <PreferenceCategory android:title="Special Intents">
+ <Preference
+ android:key="openpgp4fpr"
+ android:title="VIEW openpgp4fpr:73EE2314F65FA92EC2390D3A718C070100012282" />
+ </PreferenceCategory>
+
+</PreferenceScreen> \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/gradle/wrapper/gradle-wrapper.properties b/OpenPGP-Keychain-API/gradle/wrapper/gradle-wrapper.properties
index 425cd64c7..932184188 100644
--- a/OpenPGP-Keychain-API/gradle/wrapper/gradle-wrapper.properties
+++ b/OpenPGP-Keychain-API/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sun Feb 09 19:10:32 CET 2014
+#Fri Feb 14 01:26:40 CET 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-bin.zip
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/AndroidManifest.xml b/OpenPGP-Keychain-API/libraries/keychain-api-library/AndroidManifest.xml
index 32b4a82e5..768922c22 100644
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/AndroidManifest.xml
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/AndroidManifest.xml
@@ -5,7 +5,7 @@
android:versionName="1.0" >
<uses-sdk
- android:minSdkVersion="8"
+ android:minSdkVersion="9"
android:targetSdkVersion="19" />
<application/>
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/build.gradle b/OpenPGP-Keychain-API/libraries/keychain-api-library/build.gradle
index 2eacd2065..1d5911783 100644
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/build.gradle
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/build.gradle
@@ -1,10 +1,11 @@
+// please leave this here, so this library builds on its own
buildscript {
repositories {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.8.0'
+ classpath 'com.android.tools.build:gradle:0.8.3'
}
}
@@ -14,6 +15,19 @@ android {
compileSdkVersion 19
buildToolsVersion '19.0.1'
+ // NOTE: We are using the old folder structure to also support Eclipse
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ resources.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ }
+ }
+
// Do not abort build if lint finds errors
lintOptions {
abortOnError false
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-hdpi/ic_action_cancel_launchersize.png b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-hdpi/ic_action_cancel_launchersize.png
new file mode 100644
index 000000000..71b9118dc
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-hdpi/ic_action_cancel_launchersize.png
Binary files differ
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-mdpi/ic_action_cancel_launchersize.png b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-mdpi/ic_action_cancel_launchersize.png
new file mode 100644
index 000000000..270abf45f
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-mdpi/ic_action_cancel_launchersize.png
Binary files differ
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-xhdpi/ic_action_cancel_launchersize.png b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-xhdpi/ic_action_cancel_launchersize.png
new file mode 100644
index 000000000..1e3571fa5
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-xhdpi/ic_action_cancel_launchersize.png
Binary files differ
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-xxhdpi/ic_action_cancel_launchersize.png b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-xxhdpi/ic_action_cancel_launchersize.png
new file mode 100644
index 000000000..52044601e
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/drawable-xxhdpi/ic_action_cancel_launchersize.png
Binary files differ
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/res/values/strings.xml b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/values/strings.xml
new file mode 100644
index 000000000..a198d0b5e
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="openpgp_list_preference_none">None</string>
+
+</resources> \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl
deleted file mode 100644
index ba41de1ba..000000000
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.OpenPgpData;
-import org.openintents.openpgp.OpenPgpSignatureResult;
-import org.openintents.openpgp.OpenPgpError;
-
-interface IOpenPgpCallback {
-
- /**
- * onSuccess returns on successful OpenPGP operations.
- *
- * @param output
- * contains resulting output (decrypted content (when input was encrypted)
- * or content without signature (when input was signed-only))
- * @param signatureResult
- * signatureResult is only non-null if decryptAndVerify() was called and the content
- * was encrypted or signed-and-encrypted.
- */
- oneway void onSuccess(in OpenPgpData output, in OpenPgpSignatureResult signatureResult);
-
- /**
- * onError returns on errors or when allowUserInteraction was set to false, but user interaction
- * was required execute an OpenPGP operation.
- *
- * @param error
- * See OpenPgpError class for more information.
- */
- oneway void onError(in OpenPgpError error);
-} \ No newline at end of file
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
deleted file mode 100644
index 4ca356fad..000000000
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.OpenPgpError;
-
-interface IOpenPgpKeyIdsCallback {
-
- /**
- * onSuccess returns on successful getKeyIds operations.
- *
- * @param keyIds
- * returned key ids
- */
- oneway void onSuccess(in long[] keyIds);
-
- /**
- * onError returns on errors or when allowUserInteraction was set to false, but user interaction
- * was required execute an OpenPGP operation.
- *
- * @param error
- * See OpenPgpError class for more information.
- */
- oneway void onError(in OpenPgpError error);
-} \ No newline at end of file
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
deleted file mode 100644
index 8f9e8a0fd..000000000
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.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 {
-
- /**
- * Sign
- *
- * After successful signing, 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 callback
- * Callback where to return results
- */
- oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback);
-
- /**
- * 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
- */
- oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback);
-
- /**
- * Sign then encrypt
- *
- * After successful signing and encryption, callback's onSuccess will contain the resulting output.
- *
- * @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
- */
- 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,
- * 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);
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl
deleted file mode 100644
index 3711e4fb4..000000000
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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;
-
-// Declare OpenPgpData so AIDL can find it and knows that it implements the parcelable protocol.
-parcelable OpenPgpData; \ 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
deleted file mode 100644
index 7a6bed1e6..000000000
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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;
-
-// Declare OpenPgpError so AIDL can find it and knows that it implements the parcelable protocol.
-parcelable OpenPgpError; \ No newline at end of file
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
deleted file mode 100644
index e246792d0..000000000
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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;
-
-// Declare OpenPgpSignatureResult so AIDL can find it and knows that it implements the parcelable protocol.
-parcelable OpenPgpSignatureResult; \ No newline at end of file
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/OpenPgpData.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java
deleted file mode 100644
index 6615c2146..000000000
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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 android.net.Uri;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-
-public class OpenPgpData implements Parcelable {
- public static final int TYPE_STRING = 0;
- public static final int TYPE_BYTE_ARRAY = 1;
- public static final int TYPE_FILE_DESCRIPTOR = 2;
- public static final int TYPE_URI = 3;
-
- int type;
-
- String string;
- byte[] bytes = new byte[0];
- ParcelFileDescriptor fileDescriptor;
- Uri uri;
-
- public int getType() {
- return type;
- }
-
- public String getString() {
- return string;
- }
-
- public byte[] getBytes() {
- return bytes;
- }
-
- public ParcelFileDescriptor getFileDescriptor() {
- return fileDescriptor;
- }
-
- public Uri getUri() {
- return uri;
- }
-
- public OpenPgpData() {
-
- }
-
- /**
- * Not a real constructor. This can be used to define requested output type.
- *
- * @param type
- */
- public OpenPgpData(int type) {
- this.type = type;
- }
-
- public OpenPgpData(String string) {
- this.string = string;
- this.type = TYPE_STRING;
- }
-
- public OpenPgpData(byte[] bytes) {
- this.bytes = bytes;
- this.type = TYPE_BYTE_ARRAY;
- }
-
- public OpenPgpData(ParcelFileDescriptor fileDescriptor) {
- this.fileDescriptor = fileDescriptor;
- this.type = TYPE_FILE_DESCRIPTOR;
- }
-
- public OpenPgpData(Uri uri) {
- this.uri = uri;
- this.type = TYPE_URI;
- }
-
- public OpenPgpData(OpenPgpData b) {
- this.string = b.string;
- this.bytes = b.bytes;
- this.fileDescriptor = b.fileDescriptor;
- this.uri = b.uri;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(type);
- dest.writeString(string);
- dest.writeInt(bytes.length);
- dest.writeByteArray(bytes);
- dest.writeParcelable(fileDescriptor, 0);
- dest.writeParcelable(uri, 0);
- }
-
- public static final Creator<OpenPgpData> CREATOR = new Creator<OpenPgpData>() {
- public OpenPgpData createFromParcel(final Parcel source) {
- OpenPgpData vr = new OpenPgpData();
- vr.type = source.readInt();
- vr.string = source.readString();
- vr.bytes = new byte[source.readInt()];
- source.readByteArray(vr.bytes);
- vr.fileDescriptor = source.readParcelable(ParcelFileDescriptor.class.getClassLoader());
- vr.fileDescriptor = source.readParcelable(Uri.class.getClassLoader());
- return vr;
- }
-
- public OpenPgpData[] newArray(final int size) {
- return new OpenPgpData[size];
- }
- };
-
-}
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 <dominik@dominikschuermann.de>
- *
- * 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<ResolveInfo> 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/org/openintents/openpgp/IOpenPgpService.aidl b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/IOpenPgpService.aidl
new file mode 100644
index 000000000..578a7d4b5
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/IOpenPgpService.aidl
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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;
+
+interface IOpenPgpService {
+
+ /**
+ * General extras
+ * --------------
+ *
+ * Bundle params:
+ * int api_version (required)
+ * boolean ascii_armor (request ascii armor for ouput)
+ *
+ * returned Bundle:
+ * int result_code (0, 1, or 2 (see OpenPgpConstants))
+ * OpenPgpError error (if result_code == 0)
+ * Intent intent (if result_code == 2)
+ *
+ */
+
+ /**
+ * Sign only
+ *
+ * optional params:
+ * String passphrase (for key passphrase)
+ */
+ Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
+
+ /**
+ * Encrypt
+ *
+ * Bundle params:
+ * long[] key_ids
+ * or
+ * String[] user_ids (= emails of recipients) (if more than one key has this user_id, a PendingIntent is returned)
+ *
+ * optional params:
+ * String passphrase (for key passphrase)
+ */
+ Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
+
+ /**
+ * Sign and encrypt
+ *
+ * Bundle params:
+ * same as in encrypt()
+ */
+ 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.
+ *
+ * returned Bundle:
+ * OpenPgpSignatureResult signature_result
+ */
+ Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
+
+ /**
+ * Retrieves key ids based on given user ids (=emails)
+ *
+ * Bundle params:
+ * String[] user_ids
+ *
+ * returned Bundle:
+ * long[] key_ids
+ */
+ Bundle getKeyIds(in Bundle params);
+
+} \ No newline at end of file
diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpError.java
index f108d3169..4dd2cc641 100644
--- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpError.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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/OpenPgpSignatureResult.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpSignatureResult.java
index 829f8f8cf..16c79ca27 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/org/openintents/openpgp/OpenPgpSignatureResult.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,14 +22,14 @@ import android.os.Parcelable;
public class OpenPgpSignatureResult implements Parcelable {
// generic error on signature verification
public static final int SIGNATURE_ERROR = 0;
- // successfully verified signature, with trusted public key
- public static final int SIGNATURE_SUCCESS_TRUSTED = 1;
+ // successfully verified signature, with certified public key
+ public static final int SIGNATURE_SUCCESS_CERTIFIED = 1;
// no public key was found for this signature verification
// you can retrieve the key with
// getKeys(new String[] {String.valueOf(signatureResult.getKeyId)}, true, callback)
public static final int SIGNATURE_UNKNOWN_PUB_KEY = 2;
- // successfully verified signature, but with untrusted public key
- public static final int SIGNATURE_SUCCESS_UNTRUSTED = 3;
+ // successfully verified signature, but with certified public key
+ public static final int SIGNATURE_SUCCESS_UNCERTIFIED = 3;
int status;
boolean signatureOnly;
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpApi.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpApi.java
new file mode 100644
index 000000000..f121c345d
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpApi.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import org.openintents.openpgp.IOpenPgpService;
+import org.openintents.openpgp.OpenPgpError;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class OpenPgpApi {
+
+ IOpenPgpService mService;
+ Context mContext;
+
+ 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;
+ private static final int OPERATION_GET_KEY_IDS = 4;
+
+ public OpenPgpApi(Context context, IOpenPgpService service) {
+ this.mContext = context;
+ 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 Bundle getKeyIds(Bundle params) {
+ return executeApi(OPERATION_GET_KEY_IDS, params, null, null);
+ }
+
+ public interface IOpenPgpCallback {
+ void onReturn(final Bundle result);
+ }
+
+ private class OpenPgpAsyncTask extends AsyncTask<Void, Integer, Bundle> {
+ 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 {
+ params.putInt(OpenPgpConstants.PARAMS_API_VERSION, OpenPgpConstants.API_VERSION);
+
+ Bundle result = null;
+
+ if (operationId == OPERATION_GET_KEY_IDS) {
+ result = mService.getKeyIds(params);
+ return result;
+ } else {
+ // 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
+ 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();
+
+ // set class loader to current context to allow unparcelling
+ // of OpenPgpError and OpenPgpSignatureResult
+ // http://stackoverflow.com/a/3806769
+ result.setClassLoader(mContext.getClassLoader());
+
+ return result;
+ }
+ } 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,
+ new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage()));
+ return result;
+ }
+ }
+
+
+}
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpConstants.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpConstants.java
new file mode 100644
index 000000000..9a2d3c054
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpConstants.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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_USER_IDS = "user_ids";
+ public static final String PARAMS_KEY_IDS = "key_ids";
+ // optional parameter:
+ public static final String PARAMS_PASSPHRASE = "passphrase";
+
+ /* Service Bundle returns */
+ 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;
+ // executeServiceMethod intent and do it again with params from intent
+ public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2;
+
+ /* PendingIntent returns */
+ public static final String PI_RESULT_PARAMS = "params";
+
+}
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/org/openintents/openpgp/util/OpenPgpListPreference.java
index 4ddd97485..034186a3a 100644
--- 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/org/openintents/openpgp/util/OpenPgpListPreference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,18 +14,14 @@
* limitations under the License.
*/
-package org.openintents.openpgp;
-
-import java.util.ArrayList;
-import java.util.List;
+package org.openintents.openpgp.util;
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.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.preference.DialogPreference;
import android.util.AttributeSet;
@@ -35,33 +31,21 @@ import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.sufficientlysecure.keychain.api.R;
+
+/**
+ * Does not extend ListPreference, but is very similar to it!
+ * http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/preference/ListPreference.java/?v=source
+ */
public class OpenPgpListPreference extends DialogPreference {
- ArrayList<OpenPgpProviderEntry> mProviderList = new ArrayList<OpenPgpProviderEntry>();
+ private ArrayList<OpenPgpProviderEntry> mProviderList = new ArrayList<OpenPgpProviderEntry>();
private String mSelectedPackage;
public OpenPgpListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
-
- List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(
- new Intent(OpenPgpConstants.SERVICE_INTENT), PackageManager.GET_META_DATA);
- if (!resInfo.isEmpty()) {
- for (ResolveInfo resolveInfo : resInfo) {
- if (resolveInfo.serviceInfo == null)
- continue;
-
- String packageName = resolveInfo.serviceInfo.packageName;
- String simpleName = String.valueOf(resolveInfo.serviceInfo.loadLabel(context
- .getPackageManager()));
- 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) {
@@ -69,20 +53,42 @@ public class OpenPgpListPreference extends DialogPreference {
}
/**
- * Can be used to add "no selection"
- *
+ * Public method to add new entries for legacy applications
+ *
* @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));
+ public void addProvider(int position, String packageName, String simpleName, Drawable icon) {
+ mProviderList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon));
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
+
+ // get providers
+ mProviderList.clear();
+ Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT);
+ List<ResolveInfo> resInfo = getContext().getPackageManager().queryIntentServices(intent, 0);
+ if (!resInfo.isEmpty()) {
+ for (ResolveInfo resolveInfo : resInfo) {
+ if (resolveInfo.serviceInfo == null)
+ continue;
+
+ String packageName = resolveInfo.serviceInfo.packageName;
+ String simpleName = String.valueOf(resolveInfo.serviceInfo.loadLabel(getContext()
+ .getPackageManager()));
+ Drawable icon = resolveInfo.serviceInfo.loadIcon(getContext().getPackageManager());
+
+ mProviderList.add(new OpenPgpProviderEntry(packageName, simpleName, icon));
+ }
+ }
+
+ // add "none"-entry
+ mProviderList.add(0, new OpenPgpProviderEntry("",
+ getContext().getString(R.string.openpgp_list_preference_none),
+ getContext().getResources().getDrawable(R.drawable.ic_action_cancel_launchersize)));
+
// Init ArrayAdapter with OpenPGP Providers
ListAdapter adapter = new ArrayAdapter<OpenPgpProviderEntry>(getContext(),
android.R.layout.select_dialog_singlechoice, android.R.id.text1, mProviderList) {
@@ -99,15 +105,6 @@ public class OpenPgpListPreference extends DialogPreference {
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;
}
};
@@ -169,6 +166,16 @@ public class OpenPgpListPreference extends DialogPreference {
return getEntryByValue(mSelectedPackage);
}
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return a.getString(index);
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setValue(restoreValue ? getPersistedString(mSelectedPackage) : (String) defaultValue);
+ }
+
public String getEntryByValue(String packageName) {
for (OpenPgpProviderEntry app : mProviderList) {
if (app.packageName.equals(packageName)) {
@@ -183,14 +190,11 @@ public class OpenPgpListPreference extends DialogPreference {
private String packageName;
private String simpleName;
private Drawable icon;
- private int apiVersion;
- public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon,
- int apiVersion) {
+ public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon) {
this.packageName = packageName;
this.simpleName = simpleName;
this.icon = icon;
- this.apiVersion = apiVersion;
}
@Override
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/org/openintents/openpgp/util/OpenPgpServiceConnection.java
index f7ba06aaf..8e8812faa 100644
--- 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/org/openintents/openpgp/util/OpenPgpServiceConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.openintents.openpgp;
+package org.openintents.openpgp.util;
import org.openintents.openpgp.IOpenPgpService;
@@ -61,11 +61,12 @@ public class OpenPgpServiceConnection {
/**
* If not already bound, bind!
- *
+ *
* @return
*/
public boolean bindToService() {
- if (mService == null && !mBound) { // if not already connected
+ // if not already connected
+ if (mService == null && !mBound) {
try {
Log.d(OpenPgpConstants.TAG, "not bound yet");
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpUtils.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpUtils.java
new file mode 100644
index 000000000..ffecaceba
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpUtils.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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.Matcher;
+import java.util.regex.Pattern;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+
+public class OpenPgpUtils {
+
+ public static final Pattern PGP_MESSAGE = Pattern.compile(
+ ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
+ Pattern.DOTALL);
+
+ public static final Pattern PGP_SIGNED_MESSAGE = Pattern.compile(
+ ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
+ Pattern.DOTALL);
+
+ public static final int PARSE_RESULT_NO_PGP = -1;
+ public static final int PARSE_RESULT_MESSAGE = 0;
+ public static final int PARSE_RESULT_SIGNED_MESSAGE = 1;
+
+ public static int parseMessage(String message) {
+ Matcher matcherSigned = PGP_SIGNED_MESSAGE.matcher(message);
+ Matcher matcherMessage = PGP_MESSAGE.matcher(message);
+
+ if (matcherMessage.matches()) {
+ return PARSE_RESULT_MESSAGE;
+ } else if (matcherSigned.matches()) {
+ return PARSE_RESULT_SIGNED_MESSAGE;
+ } else {
+ return PARSE_RESULT_NO_PGP;
+ }
+ }
+
+ public static boolean isAvailable(Context context) {
+ Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT);
+ List<ResolveInfo> 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/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java
new file mode 100644
index 000000000..75d4b8c18
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * 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) {
+ Log.e(OpenPgpConstants.TAG, "TransferThread" + getId(), e);
+ }
+ try {
+ mOut.close();
+ } catch (IOException e) {
+ Log.e(OpenPgpConstants.TAG, "TransferThread" + getId(), e);
+ }
+ }
+ if (mListener != null) {
+ Log.d(OpenPgpConstants.TAG, "TransferThread " + getId() + " finished!");
+ mListener.onThreadFinished(this);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/sufficientlysecure/keychain/api/OpenKeychainIntents.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/sufficientlysecure/keychain/api/OpenKeychainIntents.java
new file mode 100644
index 000000000..15aceb534
--- /dev/null
+++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/org/sufficientlysecure/keychain/api/OpenKeychainIntents.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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.sufficientlysecure.keychain.api;
+
+public class OpenKeychainIntents {
+
+ public static final String ENCRYPT = "org.sufficientlysecure.keychain.action.ENCRYPT";
+ public static final String ENCRYPT_EXTRA_TEXT = "text"; // String
+ public static final String ENCRYPT_ASCII_ARMOR = "ascii_armor"; // boolean
+
+ public static final String DECRYPT = "org.sufficientlysecure.keychain.action.DECRYPT";
+ public static final String DECRYPT_EXTRA_TEXT = "text"; // String
+
+ public static final String IMPORT_KEY = "org.sufficientlysecure.keychain.action.IMPORT_KEY";
+ public static final String IMPORT_KEY_EXTRA_KEY_BYTES = "key_bytes"; // byte[]
+
+ public static final String IMPORT_KEY_FROM_KEYSERVER = "org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_KEYSERVER";
+ public static final String IMPORT_KEY_FROM_KEYSERVER_QUERY = "query"; // String
+ public static final String IMPORT_KEY_FROM_KEYSERVER_FINGERPRINT = "fingerprint"; // String
+
+ public static final String IMPORT_KEY_FROM_QR_CODE = "org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_QR_CODE";
+
+}
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..95f148686 100644
--- a/OpenPGP-Keychain/src/main/AndroidManifest.xml
+++ b/OpenPGP-Keychain/src/main/AndroidManifest.xml
@@ -30,7 +30,7 @@
-->
<uses-sdk
- android:minSdkVersion="8"
+ android:minSdkVersion="9"
android:targetSdkVersion="19" />
<uses-feature
@@ -153,12 +153,19 @@
android:windowSoftInputMode="stateHidden">
<!-- Keychain's own Actions -->
+ <!-- ENCRYPT with text as extra -->
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.ENCRYPT" />
<category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <!-- ENCRYPT with data Uri -->
+ <intent-filter>
+ <action android:name="org.sufficientlysecure.keychain.action.ENCRYPT" />
- <data android:mimeType="*/*" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <!-- TODO: accept other schemes! -->
+ <data android:scheme="file" />
</intent-filter>
<!-- Android's Send Action -->
<intent-filter android:label="@string/intent_send_encrypt">
@@ -176,12 +183,19 @@
android:windowSoftInputMode="stateHidden">
<!-- Keychain's own Actions -->
+ <!-- DECRYPT with text as extra -->
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.DECRYPT" />
<category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <!-- DECRYPT with data Uri -->
+ <intent-filter>
+ <action android:name="org.sufficientlysecure.keychain.action.DECRYPT" />
- <data android:mimeType="*/*" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <!-- TODO: accept other schemes! -->
+ <data android:scheme="file" />
</intent-filter>
<!-- Android's Send Action -->
<intent-filter android:label="@string/intent_send_decrypt">
@@ -282,6 +296,7 @@
<data android:mimeType="application/pgp-keys" />
</intent-filter>
<!-- Keychain's own Actions -->
+ <!-- IMPORT_KEY with files TODO: does this work? -->
<intent-filter android:label="@string/intent_import_key">
<action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY" />
@@ -289,11 +304,19 @@
<data android:mimeType="*/*" />
</intent-filter>
- <!-- IMPORT again without mimeType to also allow data only without filename -->
+ <!-- IMPORT_KEY with mimeType 'application/pgp-keys' -->
+ <intent-filter>
+ <action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <!-- mime type as defined in http://tools.ietf.org/html/rfc3156, section 7 -->
+ <data android:mimeType="application/pgp-keys" />
+ </intent-filter>
+ <!-- IMPORT_KEY without mimeType to allow import with extras Bundle -->
<intent-filter android:label="@string/intent_import_key">
<action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY" />
<action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_QR_CODE" />
- <action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_KEY_SERVER" />
+ <action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_KEYSERVER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -362,10 +385,9 @@
<activity
android:name="org.sufficientlysecure.keychain.service.remote.RemoteServiceActivity"
android:exported="false"
- android:label="@string/app_name"
- android:launchMode="singleTop"
- android:process=":remote_api"
- android:taskAffinity=":remote_api" />
+ android:label="@string/app_name" />
+ <!--android:launchMode="singleTop"-->
+ <!--android:process=":remote_api"-->
<activity
android:name="org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
@@ -392,19 +414,19 @@
</service>
<!-- Extended Remote API -->
- <service
- android:name="org.sufficientlysecure.keychain.service.remote.ExtendedApiService"
- android:enabled="true"
- android:exported="true"
- android:process=":remote_api">
- <intent-filter>
- <action android:name="org.sufficientlysecure.keychain.service.remote.IExtendedApiService" />
- </intent-filter>
-
- <meta-data
- android:name="api_version"
- android:value="1" />
- </service>
+ <!--<service-->
+ <!--android:name="org.sufficientlysecure.keychain.service.remote.ExtendedApiService"-->
+ <!--android:enabled="true"-->
+ <!--android:exported="true"-->
+ <!--android:process=":remote_api">-->
+ <!--<intent-filter>-->
+ <!--<action android:name="org.sufficientlysecure.keychain.service.remote.IExtendedApiService" />-->
+ <!--</intent-filter>-->
+
+ <!--<meta-data-->
+ <!--android:name="api_version"-->
+ <!--android:value="1" />-->
+ <!--</service>-->
<!-- TODO: authority! Make this API with content provider uris -->
<!-- <provider -->
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index 870e45ea5..1de9ab985 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -235,7 +235,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
String action = intent.getAction();
- // execute action from extra bundle
+ // executeServiceMethod action from extra bundle
if (ACTION_ENCRYPT_SIGN.equals(action)) {
try {
/* Input */
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java
deleted file mode 100644
index 555303238..000000000
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.sufficientlysecure.keychain.service.exception;
-
-public class NoUserIdsException extends Exception {
-
- private static final long serialVersionUID = 7009311527126696207L;
-
- public NoUserIdsException(String message) {
- super(message);
- }
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java
deleted file mode 100644
index 1152d6796..000000000
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.sufficientlysecure.keychain.service.exception;
-
-public class UserInteractionRequiredException extends Exception {
-
- private static final long serialVersionUID = -60128148603511936L;
-
- public UserInteractionRequiredException(String message) {
- super(message);
- }
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java
deleted file mode 100644
index 14b774eb5..000000000
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.sufficientlysecure.keychain.service.exception;
-
-public class WrongPassphraseException extends Exception {
-
- private static final long serialVersionUID = -5309689232853485740L;
-
- public WrongPassphraseException(String message) {
- super(message);
- }
-} \ No newline at end of file
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 6db091ed0..31c5662dc 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
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,108 +17,46 @@
package org.sufficientlysecure.keychain.service.remote;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.regex.Matcher;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
-import org.openintents.openpgp.IOpenPgpCallback;
-import org.openintents.openpgp.IOpenPgpKeyIdsCallback;
import org.openintents.openpgp.IOpenPgpService;
-import org.openintents.openpgp.OpenPgpData;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpSignatureResult;
+import org.openintents.openpgp.util.OpenPgpConstants;
import org.spongycastle.util.Arrays;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpOperation;
-import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
-import org.sufficientlysecure.keychain.service.exception.NoUserIdsException;
-import org.sufficientlysecure.keychain.service.exception.UserInteractionRequiredException;
-import org.sufficientlysecure.keychain.service.exception.WrongPassphraseException;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
public class OpenPgpService extends RemoteService {
- private String getCachedPassphrase(long keyId, boolean allowUserInteraction)
- throws UserInteractionRequiredException {
- String passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), keyId);
-
- if (passphrase == null) {
- if (!allowUserInteraction) {
- throw new UserInteractionRequiredException(
- "Passphrase not found in cache, please enter your passphrase!");
- }
-
- Log.d(Constants.TAG, "No passphrase! Activity required!");
-
- // start passphrase dialog
- PassphraseActivityCallback callback = new PassphraseActivityCallback();
- Bundle extras = new Bundle();
- extras.putLong(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId);
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE, callback,
- extras);
-
- if (callback.isSuccess()) {
- Log.d(Constants.TAG, "New passphrase entered!");
-
- // get again after it was entered
- passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), keyId);
- } else {
- Log.d(Constants.TAG, "Passphrase dialog canceled!");
-
- return null;
- }
-
- }
-
- return passphrase;
- }
-
- public class PassphraseActivityCallback extends UserInputCallback {
+ private static final int PRIVATE_REQUEST_CODE_PASSPHRASE = 551;
+ private static final int PRIVATE_REQUEST_CODE_USER_IDS = 552;
- private boolean success = false;
-
- public boolean isSuccess() {
- return success;
- }
-
- @Override
- public void handleUserInput(Message msg) {
- if (msg.arg1 == OKAY) {
- success = true;
- } else {
- success = false;
- }
- }
- };
/**
* Search database for key ids based on emails.
- *
+ *
* @param encryptionUserIds
* @return
*/
- private long[] getKeyIdsFromEmails(String[] encryptionUserIds, boolean allowUserInteraction)
- throws UserInteractionRequiredException {
+ private Bundle getKeyIdsFromEmails(Bundle params, String[] encryptionUserIds) {
// find key ids to given emails in database
ArrayList<Long> keyIds = new ArrayList<Long>();
@@ -152,96 +90,118 @@ public class OpenPgpService extends RemoteService {
}
// allow the user to verify pub key selection
- if (allowUserInteraction && (missingUserIdsCheck || dublicateUserIdsCheck)) {
- SelectPubKeysActivityCallback callback = new SelectPubKeysActivityCallback();
-
- Bundle extras = new Bundle();
- extras.putLongArray(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray);
- extras.putStringArrayList(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds);
- extras.putStringArrayList(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS,
- dublicateUserIds);
-
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS, callback,
- extras);
-
- if (callback.isSuccess()) {
- Log.d(Constants.TAG, "New selection of pub keys!");
- keyIdsArray = callback.getPubKeyIds();
- } else {
- Log.d(Constants.TAG, "Pub key selection canceled!");
- return null;
- }
- }
-
- // if no user interaction is allow throw exceptions on duplicate or missing pub keys
- if (!allowUserInteraction) {
- if (missingUserIdsCheck)
- throw new UserInteractionRequiredException(
- "Pub keys for these user ids are missing:" + missingUserIds.toString());
- if (dublicateUserIdsCheck)
- throw new UserInteractionRequiredException(
- "More than one pub key with these user ids exist:"
- + dublicateUserIds.toString());
+ if (missingUserIdsCheck || dublicateUserIdsCheck) {
+ // build PendingIntent for passphrase input
+ Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
+ intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS);
+ intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray);
+ intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds);
+ intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, dublicateUserIds);
+ intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
+
+ PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_USER_IDS, intent, 0);
+
+ // return PendingIntent to be executed by client
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi);
+
+ return result;
}
if (keyIdsArray.length == 0) {
return null;
}
- return keyIdsArray;
+
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS);
+ result.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS, keyIdsArray);
+ return result;
}
- public class SelectPubKeysActivityCallback extends UserInputCallback {
- public static final String PUB_KEY_IDS = "pub_key_ids";
+ private Bundle getPassphraseBundleIntent(Bundle params, long keyId) {
+ // build PendingIntent for passphrase input
+ Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
+ intent.setAction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE);
+ intent.putExtra(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId);
+ // pass params through to activity that it can be returned again later to repeat pgp operation
+ intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
+ PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_PASSPHRASE, intent, 0);
+
+ // return PendingIntent to be executed by client
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi);
+
+ return result;
+ }
- private boolean success = false;
- private long[] pubKeyIds;
- public boolean isSuccess() {
- return success;
- }
-
- public long[] getPubKeyIds() {
- return pubKeyIds;
- }
-
- @Override
- public void handleUserInput(Message msg) {
- if (msg.arg1 == OKAY) {
- success = true;
- pubKeyIds = msg.getData().getLongArray(PUB_KEY_IDS);
+ // TODO: asciiArmor?!
+ private Bundle signImpl(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output,
+ AppSettings appSettings) {
+ try {
+ // get passphrase from cache, if key has "no" passphrase, this returns an empty String
+ String passphrase;
+ if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) {
+ passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE);
} else {
- success = false;
+ passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId());
+ }
+ if (passphrase == null) {
+ // get PendingIntent for passphrase input, add it to given params and return to client
+ Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId());
+ return passphraseBundle;
}
- }
- };
- private synchronized void getKeyIdsSafe(String[] userIds, boolean allowUserInteraction,
- IOpenPgpKeyIdsCallback callback, AppSettings appSettings) {
- try {
- long[] keyIds = getKeyIdsFromEmails(userIds, allowUserInteraction);
- if (keyIds == null) {
- throw new NoUserIdsException("No user ids!");
+ // Get Input- and OutputStream from ParcelFileDescriptor
+ InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
+ OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
+ try {
+ long inputLength = is.available();
+ InputData inputData = new InputData(is, inputLength);
+
+ PgpOperation operation = new PgpOperation(getContext(), null, inputData, os);
+ operation.signText(appSettings.getKeyId(), passphrase, appSettings.getHashAlgorithm(),
+ Preferences.getPreferences(this).getForceV3Signatures());
+ } finally {
+ is.close();
+ os.close();
}
- callback.onSuccess(keyIds);
- } catch (UserInteractionRequiredException e) {
- callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage());
- } catch (NoUserIdsException e) {
- callbackOpenPgpError(callback, OpenPgpError.NO_USER_IDS, e.getMessage());
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS);
+ return result;
} catch (Exception e) {
- callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage());
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
+ result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
+ new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
+ return result;
}
}
- private synchronized void encryptAndSignSafe(OpenPgpData inputData,
- final OpenPgpData outputData, long[] keyIds, boolean allowUserInteraction,
- IOpenPgpCallback callback, AppSettings appSettings, boolean sign) {
+ private Bundle encryptAndSignImpl(Bundle params, ParcelFileDescriptor input,
+ ParcelFileDescriptor output, AppSettings appSettings,
+ boolean sign) {
try {
- // TODO: other options of OpenPgpData!
- byte[] inputBytes = getInput(inputData);
- boolean asciiArmor = false;
- if (outputData.getType() == OpenPgpData.TYPE_STRING) {
- asciiArmor = true;
+ boolean asciiArmor = params.getBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, false);
+
+ long[] keyIds;
+ if (params.containsKey(OpenPgpConstants.PARAMS_KEY_IDS)) {
+ keyIds = params.getLongArray(OpenPgpConstants.PARAMS_KEY_IDS);
+ } else {
+ // get key ids based on given user ids
+ String[] userIds = params.getStringArray(OpenPgpConstants.PARAMS_USER_IDS);
+ // give params through to activity...
+ Bundle result = getKeyIdsFromEmails(params, userIds);
+
+ if (result.getInt(OpenPgpConstants.RESULT_CODE, 0) == OpenPgpConstants.RESULT_CODE_SUCCESS) {
+ keyIds = result.getLongArray(OpenPgpConstants.PARAMS_KEY_IDS);
+ } else {
+ // if not success -> result contains a PendingIntent for user interaction
+ return result;
+ }
}
// add own key for encryption
@@ -249,349 +209,319 @@ public class OpenPgpService extends RemoteService {
keyIds[keyIds.length - 1] = appSettings.getKeyId();
// build InputData and write into OutputStream
- InputStream inputStream = new ByteArrayInputStream(inputBytes);
- long inputLength = inputBytes.length;
- InputData inputDt = new InputData(inputStream, inputLength);
-
- OutputStream outputStream = new ByteArrayOutputStream();
+ // Get Input- and OutputStream from ParcelFileDescriptor
+ InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
+ OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
+ try {
+ long inputLength = is.available();
+ InputData inputData = new InputData(is, inputLength);
+
+ PgpOperation operation = new PgpOperation(getContext(), null, inputData, os);
+ if (sign) {
+ String passphrase;
+ if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) {
+ passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE);
+ } else {
+ passphrase = PassphraseCacheService.getCachedPassphrase(getContext(),
+ appSettings.getKeyId());
+ }
+ if (passphrase == null) {
+ // get PendingIntent for passphrase input, add it to given params and return to client
+ Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId());
+ return passphraseBundle;
+ }
- PgpOperation operation = new PgpOperation(getContext(), null, inputDt, outputStream);
- if (sign) {
- String passphrase = getCachedPassphrase(appSettings.getKeyId(),
- allowUserInteraction);
- if (passphrase == null) {
- throw new WrongPassphraseException("No or wrong passphrase!");
+ operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null,
+ appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(),
+ appSettings.getHashAlgorithm(), true, passphrase);
+ } else {
+ operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null,
+ appSettings.getEncryptionAlgorithm(), Id.key.none,
+ appSettings.getHashAlgorithm(), true, null);
}
-
- operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null,
- appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(),
- appSettings.getHashAlgorithm(), true, passphrase);
- } else {
- operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null,
- appSettings.getEncryptionAlgorithm(), Id.key.none,
- appSettings.getHashAlgorithm(), true, null);
+ } finally {
+ is.close();
+ os.close();
}
- outputStream.close();
-
- byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
-
- OpenPgpData output = null;
- if (asciiArmor) {
- output = new OpenPgpData(new String(outputBytes));
- } else {
- output = new OpenPgpData(outputBytes);
- }
-
- // return over handler on client side
- callback.onSuccess(output, null);
- } catch (UserInteractionRequiredException e) {
- callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage());
- } catch (WrongPassphraseException e) {
- callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage());
- } catch (Exception e) {
- callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage());
- }
- }
-
- // TODO: asciiArmor?!
- private void signSafe(byte[] inputBytes, boolean allowUserInteraction,
- IOpenPgpCallback callback, AppSettings appSettings) {
- try {
- // build InputData and write into OutputStream
- InputStream inputStream = new ByteArrayInputStream(inputBytes);
- long inputLength = inputBytes.length;
- InputData inputData = new InputData(inputStream, inputLength);
-
- OutputStream outputStream = new ByteArrayOutputStream();
-
- String passphrase = getCachedPassphrase(appSettings.getKeyId(), allowUserInteraction);
- if (passphrase == null) {
- throw new WrongPassphraseException("No or wrong passphrase!");
- }
-
- PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream);
- operation.signText(appSettings.getKeyId(), passphrase, appSettings.getHashAlgorithm(),
- Preferences.getPreferences(this).getForceV3Signatures());
-
- outputStream.close();
-
- byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
- OpenPgpData output = new OpenPgpData(new String(outputBytes));
-
- // return over handler on client side
- callback.onSuccess(output, null);
- } catch (UserInteractionRequiredException e) {
- callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage());
- } catch (WrongPassphraseException e) {
- callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage());
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS);
+ return result;
} catch (Exception e) {
- callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage());
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
+ result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
+ new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
+ return result;
}
}
- private synchronized void decryptAndVerifySafe(byte[] inputBytes, boolean allowUserInteraction,
- IOpenPgpCallback callback, AppSettings appSettings) {
+ private Bundle decryptAndVerifyImpl(Bundle params, ParcelFileDescriptor input,
+ ParcelFileDescriptor output, AppSettings appSettings) {
try {
- // TODO: this is not really needed
- // checked if it is text with BEGIN and END tags
- String message = new String(inputBytes);
- Log.d(Constants.TAG, "in: " + message);
- boolean signedOnly = false;
- Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(message);
- if (matcher.matches()) {
- Log.d(Constants.TAG, "PGP_MESSAGE matched");
- message = matcher.group(1);
- // replace non breakable spaces
- message = message.replaceAll("\\xa0", " ");
-
- // overwrite inputBytes
- inputBytes = message.getBytes();
- } else {
- matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(message);
- if (matcher.matches()) {
- signedOnly = true;
- Log.d(Constants.TAG, "PGP_SIGNED_MESSAGE matched");
- message = matcher.group(1);
- // replace non breakable spaces
- message = message.replaceAll("\\xa0", " ");
-
- // overwrite inputBytes
- inputBytes = message.getBytes();
+ // Get Input- and OutputStream from ParcelFileDescriptor
+ InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
+ OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
+ OpenPgpSignatureResult sigResult = null;
+ try {
+
+
+ // TODOs API 2.0:
+ // implement verify-only!
+ // fix the mess: http://stackoverflow.com/questions/148130/how-do-i-peek-at-the-first-two-bytes-in-an-inputstream
+ // should we allow to decrypt everything under every key id or only the one set?
+ // TODO: instead of trying to get the passphrase before
+ // pause stream when passphrase is missing and then resume
+
+
+ // TODO: this is not really needed
+ // checked if it is text with BEGIN and END tags
+// String message = new String(inputBytes);
+// Log.d(Constants.TAG, "in: " + message);
+ boolean signedOnly = false;
+// Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(message);
+// if (matcher.matches()) {
+// Log.d(Constants.TAG, "PGP_MESSAGE matched");
+// message = matcher.group(1);
+// // replace non breakable spaces
+// message = message.replaceAll("\\xa0", " ");
+//
+// // overwrite inputBytes
+// inputBytes = message.getBytes();
+// } else {
+// matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(message);
+// if (matcher.matches()) {
+// signedOnly = true;
+// Log.d(Constants.TAG, "PGP_SIGNED_MESSAGE matched");
+// message = matcher.group(1);
+// // replace non breakable spaces
+// message = message.replaceAll("\\xa0", " ");
+//
+// // overwrite inputBytes
+// inputBytes = message.getBytes();
+// } else {
+// Log.d(Constants.TAG, "Nothing matched! Binary?");
+// }
+// }
+ // END TODO
+
+// Log.d(Constants.TAG, "in: " + new String(inputBytes));
+
+ // TODO: This allows to decrypt messages with ALL secret keys, not only the one for the
+ // app, Fix this?
+
+// String passphrase = null;
+// if (!signedOnly) {
+// // BEGIN Get key
+// // TODO: this input stream is consumed after PgpMain.getDecryptionKeyId()... do it
+// // better!
+// InputStream inputStream2 = new ByteArrayInputStream(inputBytes);
+//
+// // TODO: duplicates functions from DecryptActivity!
+// long secretKeyId;
+// try {
+// if (inputStream2.markSupported()) {
+// // should probably set this to the max size of two
+// // pgpF objects, if it even needs to be anything other
+// // than 0.
+// inputStream2.mark(200);
+// }
+// secretKeyId = PgpHelper.getDecryptionKeyId(this, inputStream2);
+// if (secretKeyId == Id.key.none) {
+// throw new PgpGeneralException(getString(R.string.error_no_secret_key_found));
+// }
+// } catch (NoAsymmetricEncryptionException e) {
+// if (inputStream2.markSupported()) {
+// inputStream2.reset();
+// }
+// secretKeyId = Id.key.symmetric;
+// if (!PgpOperation.hasSymmetricEncryption(this, inputStream2)) {
+// throw new PgpGeneralException(
+// getString(R.string.error_no_known_encryption_found));
+// }
+// // we do not support symmetric decryption from the API!
+// throw new Exception("Symmetric decryption is not supported!");
+// }
+//
+// Log.d(Constants.TAG, "secretKeyId " + secretKeyId);
+
+ // NOTE: currently this only gets the passphrase for the saved key
+ String passphrase;
+ if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) {
+ passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE);
} else {
- Log.d(Constants.TAG, "Nothing matched! Binary?");
+ passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId());
}
- }
- // END TODO
-
- Log.d(Constants.TAG, "in: " + new String(inputBytes));
-
- // TODO: This allows to decrypt messages with ALL secret keys, not only the one for the
- // app, Fix this?
-
- String passphrase = null;
- if (!signedOnly) {
- // BEGIN Get key
- // TODO: this input stream is consumed after PgpMain.getDecryptionKeyId()... do it
- // better!
- InputStream inputStream2 = new ByteArrayInputStream(inputBytes);
-
- // TODO: duplicates functions from DecryptActivity!
- long secretKeyId;
- try {
- if (inputStream2.markSupported()) {
- // should probably set this to the max size of two
- // pgpF objects, if it even needs to be anything other
- // than 0.
- inputStream2.mark(200);
- }
- secretKeyId = PgpHelper.getDecryptionKeyId(this, inputStream2);
- if (secretKeyId == Id.key.none) {
- throw new PgpGeneralException(getString(R.string.error_no_secret_key_found));
- }
- } catch (NoAsymmetricEncryptionException e) {
- if (inputStream2.markSupported()) {
- inputStream2.reset();
- }
- secretKeyId = Id.key.symmetric;
- if (!PgpOperation.hasSymmetricEncryption(this, inputStream2)) {
- throw new PgpGeneralException(
- getString(R.string.error_no_known_encryption_found));
- }
- // we do not support symmetric decryption from the API!
- throw new Exception("Symmetric decryption is not supported!");
+ if (passphrase == null) {
+ // get PendingIntent for passphrase input, add it to given params and return to client
+ Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId());
+ return passphraseBundle;
}
+// }
- Log.d(Constants.TAG, "secretKeyId " + secretKeyId);
+ // build InputData and write into OutputStream
+ long inputLength = is.available();
+ InputData inputData = new InputData(is, inputLength);
- passphrase = getCachedPassphrase(secretKeyId, allowUserInteraction);
- if (passphrase == null) {
- throw new WrongPassphraseException("No or wrong passphrase!");
- }
- }
- // build InputData and write into OutputStream
- InputStream inputStream = new ByteArrayInputStream(inputBytes);
- long inputLength = inputBytes.length;
- InputData inputData = new InputData(inputStream, inputLength);
+ Bundle outputBundle;
+ PgpOperation operation = new PgpOperation(getContext(), null, inputData, os);
+ if (signedOnly) {
+ outputBundle = operation.verifyText();
+ } else {
+ // BIG TODO: instead of trying to get the passphrase before
+ // pause stream when passphrase is missing and then resume
+ outputBundle = operation.decryptAndVerify(passphrase, false);
+ }
- OutputStream outputStream = new ByteArrayOutputStream();
+// outputStream.close();
- Bundle outputBundle;
- PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream);
- if (signedOnly) {
- outputBundle = operation.verifyText();
- } else {
- outputBundle = operation.decryptAndVerify(passphrase, false);
- }
+// byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
- outputStream.close();
+ // get signature informations from bundle
+ boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE);
- byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
+ if (signature) {
+ long signatureKeyId = outputBundle
+ .getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID);
+ String signatureUserId = outputBundle
+ .getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID);
+ boolean signatureSuccess = outputBundle
+ .getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS);
+ boolean signatureUnknown = outputBundle
+ .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN);
- // get signature informations from bundle
- boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE);
+ int signatureStatus = OpenPgpSignatureResult.SIGNATURE_ERROR;
+ if (signatureSuccess) {
+ signatureStatus = OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED;
+ } else if (signatureUnknown) {
+ signatureStatus = OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY;
+ }
- OpenPgpSignatureResult sigResult = null;
- if (signature) {
- long signatureKeyId = outputBundle
- .getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID);
- String signatureUserId = outputBundle
- .getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID);
- boolean signatureSuccess = outputBundle
- .getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS);
- boolean signatureUnknown = outputBundle
- .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN);
-
- int signatureStatus = OpenPgpSignatureResult.SIGNATURE_ERROR;
- if (signatureSuccess) {
- signatureStatus = OpenPgpSignatureResult.SIGNATURE_SUCCESS_TRUSTED;
- } else if (signatureUnknown) {
- signatureStatus = OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY;
+ sigResult = new OpenPgpSignatureResult(signatureStatus, signatureUserId,
+ signedOnly, signatureKeyId);
}
-
- sigResult = new OpenPgpSignatureResult(signatureStatus, signatureUserId,
- signedOnly, signatureKeyId);
+ } finally {
+ is.close();
+ os.close();
}
- OpenPgpData output = new OpenPgpData(new String(outputBytes));
-
- // return over handler on client side
- callback.onSuccess(output, sigResult);
- } catch (UserInteractionRequiredException e) {
- callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage());
- } catch (WrongPassphraseException e) {
- callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage());
+
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS);
+ result.putParcelable(OpenPgpConstants.RESULT_SIGNATURE, sigResult);
+ return result;
} catch (Exception e) {
- callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage());
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
+ result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
+ new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
+ return result;
}
}
+ private Bundle getKeyIdsImpl(Bundle params) {
+ // get key ids based on given user ids
+ String[] userIds = params.getStringArray(OpenPgpConstants.PARAMS_USER_IDS);
+ Bundle result = getKeyIdsFromEmails(params, userIds);
+ return result;
+ }
+
/**
- * Returns error to IOpenPgpCallback
- *
- * @param callback
- * @param errorId
- * @param message
+ * Checks that params != null and API version fits
+ *
+ * @param params
+ * @return
*/
- private void callbackOpenPgpError(IOpenPgpCallback callback, int errorId, String message) {
- try {
- callback.onError(new OpenPgpError(0, message));
- } catch (Exception t) {
- Log.e(Constants.TAG,
- "Exception while returning OpenPgpError to client via callback.onError()", t);
+ private Bundle checkRequirements(Bundle params) {
+ // params Bundle is required!
+ 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;
}
- }
- private void callbackOpenPgpError(IOpenPgpKeyIdsCallback callback, int errorId, String message) {
- try {
- callback.onError(new OpenPgpError(0, message));
- } catch (Exception t) {
- Log.e(Constants.TAG,
- "Exception while returning OpenPgpError to client via callback.onError()", t);
+ // version code is required and needs to correspond to version code of service!
+ if (params.getInt(OpenPgpConstants.PARAMS_API_VERSION) != OpenPgpConstants.API_VERSION) {
+ 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);
+ return result;
}
+
+ // check if caller is allowed to access openpgp keychain
+ Bundle result = isAllowed(params);
+ if (result != null) {
+ return result;
+ }
+
+ return null;
}
+ // TODO: multi-threading
private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() {
@Override
- public void encrypt(final OpenPgpData input, final OpenPgpData output, final long[] keyIds,
- final IOpenPgpCallback callback) throws RemoteException {
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- encryptAndSignSafe(input, output, keyIds, true, callback, settings, false);
- }
- };
+ public Bundle sign(Bundle params, final ParcelFileDescriptor input, final ParcelFileDescriptor output) {
+ final AppSettings appSettings = getAppSettings();
- checkAndEnqueue(r);
- }
-
- @Override
- public void signAndEncrypt(final OpenPgpData input, final OpenPgpData output,
- final long[] keyIds, final IOpenPgpCallback callback) throws RemoteException {
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- encryptAndSignSafe(input, output, keyIds, true, callback, settings, true);
- }
- };
+ Bundle errorResult = checkRequirements(params);
+ if (errorResult != null) {
+ return errorResult;
+ }
- checkAndEnqueue(r);
+ return signImpl(params, input, output, appSettings);
}
@Override
- public void sign(final OpenPgpData input, final OpenPgpData output,
- final IOpenPgpCallback callback) throws RemoteException {
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- signSafe(getInput(input), true, callback, settings);
- }
- };
+ public Bundle encrypt(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) {
+ final AppSettings appSettings = getAppSettings();
+
+ Bundle errorResult = checkRequirements(params);
+ if (errorResult != null) {
+ return errorResult;
+ }
- checkAndEnqueue(r);
+ return encryptAndSignImpl(params, input, output, appSettings, false);
}
@Override
- public void decryptAndVerify(final OpenPgpData input, final OpenPgpData output,
- final IOpenPgpCallback callback) throws RemoteException {
+ public Bundle signAndEncrypt(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) {
+ final AppSettings appSettings = getAppSettings();
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- decryptAndVerifySafe(getInput(input), true, callback, settings);
- }
- };
+ Bundle errorResult = checkRequirements(params);
+ if (errorResult != null) {
+ return errorResult;
+ }
- checkAndEnqueue(r);
+ return encryptAndSignImpl(params, input, output, appSettings, true);
}
@Override
- public void getKeyIds(final String[] userIds, final boolean allowUserInteraction,
- final IOpenPgpKeyIdsCallback callback) throws RemoteException {
-
- final AppSettings settings = getAppSettings();
+ public Bundle decryptAndVerify(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) {
+ final AppSettings appSettings = getAppSettings();
- Runnable r = new Runnable() {
- @Override
- public void run() {
- getKeyIdsSafe(userIds, allowUserInteraction, callback, settings);
- }
- };
+ Bundle errorResult = checkRequirements(params);
+ if (errorResult != null) {
+ return errorResult;
+ }
- checkAndEnqueue(r);
+ return decryptAndVerifyImpl(params, input, output, appSettings);
}
- };
-
- private static byte[] getInput(OpenPgpData data) {
- // TODO: support Uri and ParcelFileDescriptor
-
- byte[] inBytes = null;
- switch (data.getType()) {
- case OpenPgpData.TYPE_STRING:
- inBytes = data.getString().getBytes();
- break;
-
- case OpenPgpData.TYPE_BYTE_ARRAY:
- inBytes = data.getBytes();
- break;
+ @Override
+ public Bundle getKeyIds(Bundle params) {
+ Bundle errorResult = checkRequirements(params);
+ if (errorResult != null) {
+ return errorResult;
+ }
- default:
- Log.e(Constants.TAG, "Uri and ParcelFileDescriptor not supported right now!");
- break;
+ return getKeyIdsImpl(params);
}
- return inBytes;
- }
+ };
@Override
public IBinder onBind(Intent intent) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java
index bc513d532..cfd2b9ec3 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,17 +19,16 @@ package org.sufficientlysecure.keychain.service.remote;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.TimeUnit;
+import org.openintents.openpgp.OpenPgpError;
+import org.openintents.openpgp.util.OpenPgpConstants;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.exception.WrongPackageSignatureException;
import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.PausableThreadPoolExecutor;
+import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@@ -50,66 +49,19 @@ import android.os.Messenger;
public abstract class RemoteService extends Service {
Context mContext;
- private final ArrayBlockingQueue<Runnable> mPoolQueue = new ArrayBlockingQueue<Runnable>(100);
- // TODO: Are these parameters okay?
- private PausableThreadPoolExecutor mThreadPool = new PausableThreadPoolExecutor(2, 4, 10,
- TimeUnit.SECONDS, mPoolQueue);
+ private static final int PRIVATE_REQUEST_CODE_REGISTER = 651;
+ private static final int PRIVATE_REQUEST_CODE_ERROR = 652;
- private final Object userInputLock = new Object();
-
- /**
- * Override handleUserInput() to handle OKAY (1) and CANCEL (0). After handling the waiting
- * threads will be notified and the queue resumed
- */
- protected class UserInputCallback extends BaseCallback {
-
- public void handleUserInput(Message msg) {
- }
-
- @Override
- public boolean handleMessage(Message msg) {
- handleUserInput(msg);
-
- // resume
- synchronized (userInputLock) {
- userInputLock.notifyAll();
- }
- mThreadPool.resume();
- return true;
- }
-
- }
-
- /**
- * Extends Handler.Callback with OKAY (1), CANCEL (0) variables
- */
- private class BaseCallback implements Handler.Callback {
- public static final int OKAY = 1;
- public static final int CANCEL = 0;
-
- @Override
- public boolean handleMessage(Message msg) {
- return false;
- }
-
- }
public Context getContext() {
return mContext;
}
- /**
- * Should be used from Stub implementations of AIDL interfaces to enqueue a runnable for
- * execution
- *
- * @param r
- */
- protected void checkAndEnqueue(Runnable r) {
+ protected Bundle isAllowed(Bundle params) {
try {
if (isCallerAllowed(false)) {
- mThreadPool.execute(r);
- Log.d(Constants.TAG, "Enqueued runnable…");
+ return null;
} else {
String[] callingPackages = getPackageManager().getPackagesForUid(
Binder.getCallingUid());
@@ -121,32 +73,46 @@ public abstract class RemoteService extends Service {
packageSignature = getPackageSignature(packageName);
} catch (NameNotFoundException e) {
Log.e(Constants.TAG, "Should not happen, returning!", e);
- return;
- }
- Log.e(Constants.TAG,
- "Not allowed to use service! Starting activity for registration!");
- Bundle extras = new Bundle();
- extras.putString(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
- extras.putByteArray(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature);
- RegisterActivityCallback callback = new RegisterActivityCallback();
-
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_REGISTER, callback,
- extras);
-
- if (callback.isAllowed()) {
- mThreadPool.execute(r);
- Log.d(Constants.TAG, "Enqueued runnable…");
- } else {
- Log.d(Constants.TAG, "User disallowed app!");
+ // return error
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
+ result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
+ new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
+ return result;
}
+ Log.e(Constants.TAG, "Not allowed to use service! return PendingIntent for registration!");
+
+ Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
+ intent.setAction(RemoteServiceActivity.ACTION_REGISTER);
+ intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
+ intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature);
+ intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
+
+ PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_REGISTER, intent, 0);
+
+ // return PendingIntent to be executed by client
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi);
+
+ return result;
}
} catch (WrongPackageSignatureException e) {
- Log.e(Constants.TAG, e.getMessage());
+ Log.e(Constants.TAG, "wrong signature!", e);
+
+ Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
+ intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE);
+ intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, getString(R.string.api_error_wrong_signature));
+ intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
+
+ PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_ERROR, intent, 0);
+
+ // return PendingIntent to be executed by client
+ Bundle result = new Bundle();
+ result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi);
- Bundle extras = new Bundle();
- extras.putString(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
- getString(R.string.api_error_wrong_signature));
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_ERROR_MESSAGE, null, extras);
+ return result;
}
}
@@ -161,40 +127,8 @@ public abstract class RemoteService extends Service {
}
/**
- * Locks current thread and pauses execution of runnables and starts activity for user input
- *
- * @param action
- * @param messenger
- * @param extras
- */
- protected void pauseAndStartUserInteraction(String action, BaseCallback callback, Bundle extras) {
- synchronized (userInputLock) {
- mThreadPool.pause();
-
- Log.d(Constants.TAG, "starting activity...");
- Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setAction(action);
-
- Messenger messenger = new Messenger(new Handler(getMainLooper(), callback));
-
- extras.putParcelable(RemoteServiceActivity.EXTRA_MESSENGER, messenger);
- intent.putExtras(extras);
-
- startActivity(intent);
-
- // lock current thread for user input
- try {
- userInputLock.wait();
- } catch (InterruptedException e) {
- Log.e(Constants.TAG, "CryptoService", e);
- }
- }
- }
-
- /**
* Retrieves AppSettings from database for the application calling this remote service
- *
+ *
* @return
*/
protected AppSettings getAppSettings() {
@@ -215,66 +149,11 @@ public abstract class RemoteService extends Service {
return null;
}
- class RegisterActivityCallback extends BaseCallback {
- public static final String PACKAGE_NAME = "package_name";
-
- private boolean allowed = false;
- private String packageName;
-
- public boolean isAllowed() {
- return allowed;
- }
-
- public String getPackageName() {
- return packageName;
- }
-
- @Override
- public boolean handleMessage(Message msg) {
- if (msg.arg1 == OKAY) {
- allowed = true;
- packageName = msg.getData().getString(PACKAGE_NAME);
-
- // resume threads
- try {
- if (isPackageAllowed(packageName)) {
- synchronized (userInputLock) {
- userInputLock.notifyAll();
- }
- mThreadPool.resume();
- } else {
- // Should not happen!
- Log.e(Constants.TAG, "Should not happen! Emergency shutdown!");
- mThreadPool.shutdownNow();
- }
- } catch (WrongPackageSignatureException e) {
- Log.e(Constants.TAG, e.getMessage());
-
- Bundle extras = new Bundle();
- extras.putString(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
- getString(R.string.api_error_wrong_signature));
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_ERROR_MESSAGE, null,
- extras);
- }
- } else {
- allowed = false;
-
- synchronized (userInputLock) {
- userInputLock.notifyAll();
- }
- mThreadPool.resume();
- }
- return true;
- }
-
- }
-
/**
* Checks if process that binds to this service (i.e. the package name corresponding to the
* process) is in the list of allowed package names.
- *
- * @param allowOnlySelf
- * allow only Keychain app itself
+ *
+ * @param allowOnlySelf allow only Keychain app itself
* @return true if process is allowed to use this service
* @throws WrongPackageSignatureException
*/
@@ -308,7 +187,7 @@ public abstract class RemoteService extends Service {
/**
* Checks if packageName is a registered app for the API. Does not return true for own package!
- *
+ *
* @param packageName
* @return
* @throws WrongPackageSignatureException
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
index 7ab39fce1..af8e3ade8 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,8 +17,15 @@
package org.sufficientlysecure.keychain.service.remote;
-import java.util.ArrayList;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v7.app.ActionBarActivity;
+import android.view.View;
+import org.openintents.openpgp.util.OpenPgpConstants;
import org.sufficientlysecure.htmltextview.HtmlTextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
@@ -30,15 +37,7 @@ import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.support.v7.app.ActionBarActivity;
-import android.view.View;
-import android.widget.Toast;
+import java.util.ArrayList;
public class RemoteServiceActivity extends ActionBarActivity {
@@ -64,17 +63,11 @@ public class RemoteServiceActivity extends ActionBarActivity {
// error message
public static final String EXTRA_ERROR_MESSAGE = "error_message";
- private Messenger mMessenger;
-
// register view
private AppSettingsFragment mSettingsFragment;
// select pub keys view
private SelectPublicKeyFragment mSelectFragment;
- // has the user clicked one of the buttons
- // or do we need to handle the callback in onStop()
- private boolean finishHandled;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -82,36 +75,12 @@ public class RemoteServiceActivity extends ActionBarActivity {
handleActions(getIntent(), savedInstanceState);
}
- @Override
- protected void onStop() {
- super.onStop();
-
- if (!finishHandled) {
- Message msg = Message.obtain();
- msg.arg1 = RemoteService.RegisterActivityCallback.CANCEL;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
- }
- }
-
protected void handleActions(Intent intent, Bundle savedInstanceState) {
- finishHandled = false;
String action = intent.getAction();
- Bundle extras = intent.getExtras();
+ final Bundle extras = intent.getExtras();
- if (extras == null) {
- extras = new Bundle();
- }
- mMessenger = extras.getParcelable(EXTRA_MESSENGER);
-
- /**
- * com.android.crypto actions
- */
if (ACTION_REGISTER.equals(action)) {
final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
@@ -131,37 +100,21 @@ public class RemoteServiceActivity extends ActionBarActivity {
ProviderHelper.insertApiApp(RemoteServiceActivity.this,
mSettingsFragment.getAppSettings());
- Message msg = Message.obtain();
- msg.arg1 = RemoteService.RegisterActivityCallback.OKAY;
- Bundle data = new Bundle();
- data.putString(RemoteService.RegisterActivityCallback.PACKAGE_NAME,
- packageName);
- msg.setData(data);
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
-
- finishHandled = true;
- finish();
+ // give params through for new service call
+ Bundle oldParams = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS);
+
+ Intent finishIntent = new Intent();
+ finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, oldParams);
+ RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent);
+ RemoteServiceActivity.this.finish();
}
}
}, R.string.api_register_disallow, new View.OnClickListener() {
@Override
public void onClick(View v) {
// Disallow
-
- Message msg = Message.obtain();
- msg.arg1 = RemoteService.RegisterActivityCallback.CANCEL;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
-
- finishHandled = true;
- finish();
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
+ RemoteServiceActivity.this.finish();
}
}
);
@@ -175,8 +128,9 @@ public class RemoteServiceActivity extends ActionBarActivity {
mSettingsFragment.setAppSettings(settings);
} else if (ACTION_CACHE_PASSPHRASE.equals(action)) {
long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID);
+ Bundle oldParams = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS);
- showPassphraseDialog(secretKeyId);
+ showPassphraseDialog(oldParams, secretKeyId);
} else if (ACTION_SELECT_PUB_KEYS.equals(action)) {
long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
ArrayList<String> missingUserIds = intent
@@ -184,8 +138,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
ArrayList<String> dublicateUserIds = intent
.getStringArrayListExtra(EXTRA_DUBLICATE_USER_IDS);
- String text = new String();
- text += "<b>" + getString(R.string.api_select_pub_keys_text) + "</b>";
+ // TODO: do this with spannable instead of HTML to prevent parsing failures with weird user ids
+ String text = "<b>" + getString(R.string.api_select_pub_keys_text) + "</b>";
text += "<br/><br/>";
if (missingUserIds != null && missingUserIds.size() > 0) {
text += getString(R.string.api_select_pub_keys_missing_text);
@@ -212,40 +166,22 @@ public class RemoteServiceActivity extends ActionBarActivity {
new View.OnClickListener() {
@Override
public void onClick(View v) {
- // ok
-
- Message msg = Message.obtain();
- msg.arg1 = OpenPgpService.SelectPubKeysActivityCallback.OKAY;
- Bundle data = new Bundle();
- data.putLongArray(
- OpenPgpService.SelectPubKeysActivityCallback.PUB_KEY_IDS,
+ // add key ids to params Bundle for new request
+ Bundle params = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS);
+ params.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS,
mSelectFragment.getSelectedMasterKeyIds());
- msg.setData(data);
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
- finishHandled = true;
- finish();
+ Intent finishIntent = new Intent();
+ finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
+ RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent);
+ RemoteServiceActivity.this.finish();
}
}, R.string.btn_do_not_save, new View.OnClickListener() {
@Override
public void onClick(View v) {
// cancel
-
- Message msg = Message.obtain();
- msg.arg1 = OpenPgpService.SelectPubKeysActivityCallback.CANCEL;
- ;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
-
- finishHandled = true;
- finish();
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
+ RemoteServiceActivity.this.finish();
}
}
);
@@ -278,8 +214,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
} else if (ACTION_ERROR_MESSAGE.equals(action)) {
String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE);
- String text = new String();
- text += "<font color=\"red\">" + errorMessage + "</font>";
+ String text = "<font color=\"red\">" + errorMessage + "</font>";
// Inflate a "Done" custom action bar view
ActionBarHelper.setDoneView(getSupportActionBar(), R.string.btn_okay,
@@ -287,7 +222,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
@Override
public void onClick(View v) {
- finish();
+ RemoteServiceActivity.this.setResult(RESULT_OK);
+ RemoteServiceActivity.this.finish();
}
});
@@ -297,7 +233,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
HtmlTextView textView = (HtmlTextView) findViewById(R.id.api_app_error_message_text);
textView.setHtmlFromString(text);
} else {
- Log.e(Constants.TAG, "Wrong action!");
+ Log.e(Constants.TAG, "Action does not exist!");
+ setResult(RESULT_CANCELED);
finish();
}
}
@@ -307,31 +244,21 @@ public class RemoteServiceActivity extends ActionBarActivity {
* encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks
* for a symmetric passphrase
*/
- private void showPassphraseDialog(long secretKeyId) {
+ private void showPassphraseDialog(final Bundle params, long secretKeyId) {
// Message is received after passphrase is cached
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
- Message msg = Message.obtain();
- msg.arg1 = OpenPgpService.PassphraseActivityCallback.OKAY;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
+ // return given params again, for calling the service method again
+ Intent finishIntent = new Intent();
+ finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
+ RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent);
} else {
- Message msg = Message.obtain();
- msg.arg1 = OpenPgpService.PassphraseActivityCallback.CANCEL;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
}
- finishHandled = true;
- finish();
+ RemoteServiceActivity.this.finish();
}
};
@@ -344,9 +271,12 @@ public class RemoteServiceActivity extends ActionBarActivity {
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
} catch (PgpGeneralException e) {
- Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
- // send message to handler to start encryption directly
- returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
+ Log.d(Constants.TAG, "No passphrase for this secret key, do pgp operation directly!");
+ // return given params again, for calling the service method again
+ Intent finishIntent = new Intent();
+ finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
+ setResult(RESULT_OK, finishIntent);
+ finish();
}
}
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java
index cef002265..cc08548e8 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java
@@ -1,4 +1,4 @@
-package org.sufficientlysecure.keychain.service.exception;
+package org.sufficientlysecure.keychain.service.remote;
public class WrongPackageSignatureException extends Exception {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
index 3dd077d12..b8eed83c9 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -300,7 +300,7 @@ public class DecryptActivity extends DrawerActivity {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
// handle like normal text decryption, override action and extras to later
- // execute ACTION_DECRYPT in main actions
+ // executeServiceMethod ACTION_DECRYPT in main actions
extras.putString(EXTRA_TEXT, sharedText);
action = ACTION_DECRYPT;
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index 81446db99..85bfba224 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -173,7 +173,7 @@ public class EncryptActivity extends DrawerActivity {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
// handle like normal text encryption, override action and extras to later
- // execute ACTION_ENCRYPT in main actions
+ // executeServiceMethod ACTION_ENCRYPT in main actions
extras.putString(EXTRA_TEXT, sharedText);
extras.putBoolean(EXTRA_ASCII_ARMOR, true);
action = ACTION_ENCRYPT;
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index e0f25b632..1864e0d9d 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -57,6 +57,7 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
+ "IMPORT_KEY_FROM_QR_CODE";
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER = Constants.INTENT_PREFIX
+ "IMPORT_KEY_FROM_KEYSERVER";
+ // TODO: implement:
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN = Constants.INTENT_PREFIX
+ "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN";
diff --git a/OpenPGP-Keychain/src/main/res/values/strings.xml b/OpenPGP-Keychain/src/main/res/values/strings.xml
index 88ad10a0a..d34fe0105 100644
--- a/OpenPGP-Keychain/src/main/res/values/strings.xml
+++ b/OpenPGP-Keychain/src/main/res/values/strings.xml
@@ -295,7 +295,7 @@
<string name="progress_saving">saving…</string>
<string name="progress_importing">importing…</string>
<string name="progress_exporting">exporting…</string>
- <string name="progress_generating">generating key, this can take a while…</string>
+ <string name="progress_generating">generating key, this can take up to 3 minutes…</string>
<string name="progress_building_key">building key…</string>
<string name="progress_preparing_master_key">preparing master key…</string>
<string name="progress_certifying_master_key">certifying master key…</string>
@@ -383,7 +383,7 @@
<string name="api_settings_revoke">Revoke access</string>
<string name="api_settings_package_name">Package Name</string>
<string name="api_settings_package_signature">SHA-256 of Package Signature</string>
- <string name="api_register_text">The following application requests access to OpenPGP Keychain.\n\nAllow permanent access?</string>
+ <string name="api_register_text">The displayed application requests access to OpenPGP Keychain.\nAllow access?\n\nWARNING: If you do not know why this screen appeared, disallow access! You can revoke access later using the \'Registered Applications\' screen.</string>
<string name="api_register_allow">Allow access</string>
<string name="api_register_disallow">Disallow access</string>
<string name="api_register_error_select_key">Please select a key!</string>
diff --git a/README.md b/README.md
index a2fc5c242..01b91725d 100644
--- a/README.md
+++ b/README.md
@@ -87,8 +87,7 @@ To do automatic encryption/decryption/sign/verify use the OpenPGP Remote API.
* NFC (``android.nfc.action.NDEF_DISCOVERED``) on mime type ``application/pgp-keys`` (as specified in http://tools.ietf.org/html/rfc3156, section 7)
### OpenPGP Remote API
-To do asyncronous fast encryption/decryption/sign/verify operations bind to the OpenPGP remote service.
-The API Demo contains all required AIDL files and a demo activity.
+To do fast encryption/decryption/sign/verify operations without user interaction bind to the OpenPGP remote service.
#### Try out the API
Keychain: https://play.google.com/store/apps/details?id=org.sufficientlysecure.keychain
@@ -99,45 +98,25 @@ All apps wanting to use this generic API
just need to include the AIDL files and connect to the service. Other
OpenPGP apps can implement a service based on this AIDL definition.
-The API is designed to be as easy as possible to use by apps like
-K-9 Mail. The service definition defines
-sign/encrypt/signAndEncrypt/decryptAndVerify [1].
+The API is designed to be as easy as possible to use by apps like K-9 Mail.
+The service definition defines sign, encrypt, signAndEncrypt, decryptAndVerify, and getKeyIds.
-As can be seen the apps themselves never need handle key ids directly.
-Only user ids (emails) are used to define recipients. If more than one
-pub key exists for an email, OpenPGP Keychain will handle the problem by
-showing a selection screen.
+As can be seen in the API Demo, the apps themselves never need to handle key ids directly.
+You can use user ids (emails) to define recipients.
+If more than one public key exists for an email, OpenPGP Keychain will handle the problem by showing a selection screen. Additionally, it is also possible to use key ids.
-Also app devs never need to fiddle with private keys. On first
-operation, OpenPGP Keychain shows an activity to allow or disallow
-access, while also allowing to choose the private key used for this app.
-Please try the Demo app out to see how it works [4].
+Also app devs never need to fiddle with private keys.
+On first operation, OpenPGP Keychain shows an activity to allow or disallow access, while also allowing to choose the private key used for this app.
+Please try the Demo app out to see how it works.
#### Integration
-The API is defined as AIDL interfaces in org.openintents.openpgp packge
-[2]. All files from [2] needs to be included in the project.
+Copy the api library from "libraries/keychain-api-library" to your project and add it as an dependency to your gradle build.
+Inspect the ode found in "OpenPGP-Keychain-API" to understand how to use the API.
-Using the OpenPgpServiceConnection.java [3] you can choose to which
-OpenPGP provider you want to connect (other pgp apps can implement the
-interfaces). They can be queried as shown in the demo app (see [3] how
-to query). If other OpenPGP apps implement the service, no additional
-code is required in k9mail per provider. See [3] for a complete example
-for integration.
-
-[1] https://github.com/openpgp-keychain/openpgp-keychain/blob/master/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/IOpenPgpService.aidl
-[2] https://github.com/openpgp-keychain/openpgp-keychain/tree/master/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp
-[3] https://github.com/openpgp-keychain/openpgp-keychain/blob/master/OpenPGP-Keychain-API-Demo/src/org/openintents/openpgp/OpenPgpServiceConnection.java
-[3] https://github.com/openpgp-keychain/openpgp-keychain/blob/master/OpenPGP-Keychain-API-Demo/src/org/sufficientlysecure/keychain/demo/OpenPgpProviderActivity.java
-[4] https://play.google.com/store/apps/details?id=org.sufficientlysecure.keychain.demo
-
-## Extended Remote API
-
-TODO
## Libraries
-
### ZXing Barcode Scanner Android Integration
Classes can be found under "libraries/zxing-android-integration/".
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl b/Resources/old extended service/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl
index f69f66fd7..f69f66fd7 100644
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl
+++ b/Resources/old extended service/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl b/Resources/old extended service/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl
index 669bd31b5..669bd31b5 100644
--- a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl
+++ b/Resources/old extended service/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java b/Resources/old extended service/src/main/java/ExtendedApiService.java
index 427e6bb8f..427e6bb8f 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java
+++ b/Resources/old extended service/src/main/java/ExtendedApiService.java
diff --git a/build.gradle b/build.gradle
index a84ab6b3c..86c40fa3a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.8.0'
+ classpath 'com.android.tools.build:gradle:0.8.3'
}
}
diff --git a/libraries/keychain-api-library/src/main/AndroidManifest.xml b/libraries/keychain-api-library/AndroidManifest.xml
index 32b4a82e5..768922c22 100644
--- a/libraries/keychain-api-library/src/main/AndroidManifest.xml
+++ b/libraries/keychain-api-library/AndroidManifest.xml
@@ -5,7 +5,7 @@
android:versionName="1.0" >
<uses-sdk
- android:minSdkVersion="8"
+ android:minSdkVersion="9"
android:targetSdkVersion="19" />
<application/>
diff --git a/libraries/keychain-api-library/build.gradle b/libraries/keychain-api-library/build.gradle
index 5436ecd0a..1d5911783 100644
--- a/libraries/keychain-api-library/build.gradle
+++ b/libraries/keychain-api-library/build.gradle
@@ -1,10 +1,33 @@
-apply plugin: 'android-library'
+// please leave this here, so this library builds on its own
+buildscript {
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:0.8.3'
+ }
+}
+apply plugin: 'android-library'
android {
compileSdkVersion 19
buildToolsVersion '19.0.1'
+ // NOTE: We are using the old folder structure to also support Eclipse
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ resources.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ }
+ }
+
// Do not abort build if lint finds errors
lintOptions {
abortOnError false
diff --git a/libraries/keychain-api-library/res/drawable-hdpi/ic_action_cancel_launchersize.png b/libraries/keychain-api-library/res/drawable-hdpi/ic_action_cancel_launchersize.png
new file mode 100644
index 000000000..71b9118dc
--- /dev/null
+++ b/libraries/keychain-api-library/res/drawable-hdpi/ic_action_cancel_launchersize.png
Binary files differ
diff --git a/libraries/keychain-api-library/res/drawable-mdpi/ic_action_cancel_launchersize.png b/libraries/keychain-api-library/res/drawable-mdpi/ic_action_cancel_launchersize.png
new file mode 100644
index 000000000..270abf45f
--- /dev/null
+++ b/libraries/keychain-api-library/res/drawable-mdpi/ic_action_cancel_launchersize.png
Binary files differ
diff --git a/libraries/keychain-api-library/res/drawable-xhdpi/ic_action_cancel_launchersize.png b/libraries/keychain-api-library/res/drawable-xhdpi/ic_action_cancel_launchersize.png
new file mode 100644
index 000000000..1e3571fa5
--- /dev/null
+++ b/libraries/keychain-api-library/res/drawable-xhdpi/ic_action_cancel_launchersize.png
Binary files differ
diff --git a/libraries/keychain-api-library/res/drawable-xxhdpi/ic_action_cancel_launchersize.png b/libraries/keychain-api-library/res/drawable-xxhdpi/ic_action_cancel_launchersize.png
new file mode 100644
index 000000000..52044601e
--- /dev/null
+++ b/libraries/keychain-api-library/res/drawable-xxhdpi/ic_action_cancel_launchersize.png
Binary files differ
diff --git a/libraries/keychain-api-library/res/values/strings.xml b/libraries/keychain-api-library/res/values/strings.xml
new file mode 100644
index 000000000..a198d0b5e
--- /dev/null
+++ b/libraries/keychain-api-library/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="openpgp_list_preference_none">None</string>
+
+</resources> \ No newline at end of file
diff --git a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl
deleted file mode 100644
index ba41de1ba..000000000
--- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpCallback.aidl
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.OpenPgpData;
-import org.openintents.openpgp.OpenPgpSignatureResult;
-import org.openintents.openpgp.OpenPgpError;
-
-interface IOpenPgpCallback {
-
- /**
- * onSuccess returns on successful OpenPGP operations.
- *
- * @param output
- * contains resulting output (decrypted content (when input was encrypted)
- * or content without signature (when input was signed-only))
- * @param signatureResult
- * signatureResult is only non-null if decryptAndVerify() was called and the content
- * was encrypted or signed-and-encrypted.
- */
- oneway void onSuccess(in OpenPgpData output, in OpenPgpSignatureResult signatureResult);
-
- /**
- * onError returns on errors or when allowUserInteraction was set to false, but user interaction
- * was required execute an OpenPGP operation.
- *
- * @param error
- * See OpenPgpError class for more information.
- */
- oneway void onError(in OpenPgpError error);
-} \ No newline at end of file
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
deleted file mode 100644
index 4ca356fad..000000000
--- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpKeyIdsCallback.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.OpenPgpError;
-
-interface IOpenPgpKeyIdsCallback {
-
- /**
- * onSuccess returns on successful getKeyIds operations.
- *
- * @param keyIds
- * returned key ids
- */
- oneway void onSuccess(in long[] keyIds);
-
- /**
- * onError returns on errors or when allowUserInteraction was set to false, but user interaction
- * was required execute an OpenPGP operation.
- *
- * @param error
- * See OpenPgpError class for more information.
- */
- oneway void onError(in OpenPgpError error);
-} \ No newline at end of file
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
deleted file mode 100644
index 8f9e8a0fd..000000000
--- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/IOpenPgpService.aidl
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.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 {
-
- /**
- * Sign
- *
- * After successful signing, 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 callback
- * Callback where to return results
- */
- oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback);
-
- /**
- * 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
- */
- oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback);
-
- /**
- * Sign then encrypt
- *
- * After successful signing and encryption, callback's onSuccess will contain the resulting output.
- *
- * @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
- */
- 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,
- * 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);
-
-} \ No newline at end of file
diff --git a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl b/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl
deleted file mode 100644
index 3711e4fb4..000000000
--- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpData.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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;
-
-// Declare OpenPgpData so AIDL can find it and knows that it implements the parcelable protocol.
-parcelable OpenPgpData; \ 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
deleted file mode 100644
index 7a6bed1e6..000000000
--- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpError.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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;
-
-// Declare OpenPgpError so AIDL can find it and knows that it implements the parcelable protocol.
-parcelable OpenPgpError; \ No newline at end of file
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
deleted file mode 100644
index e246792d0..000000000
--- a/libraries/keychain-api-library/src/main/aidl/org/openintents/openpgp/OpenPgpSignatureResult.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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;
-
-// Declare OpenPgpSignatureResult so AIDL can find it and knows that it implements the parcelable protocol.
-parcelable OpenPgpSignatureResult; \ No newline at end of file
diff --git a/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl b/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl
deleted file mode 100644
index f69f66fd7..000000000
--- a/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.sufficientlysecure.keychain.service.remote;
-
-interface IExtendedApiCallback {
-
- oneway void onSuccess(in byte[] outputBytes);
-
- oneway void onError(in String error);
-} \ No newline at end of file
diff --git a/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl b/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl
deleted file mode 100644
index 669bd31b5..000000000
--- a/libraries/keychain-api-library/src/main/aidl/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.sufficientlysecure.keychain.service.remote;
-
-import org.sufficientlysecure.keychain.service.remote.IExtendedApiCallback;
-
-/**
- * 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 IExtendedApiService {
-
- /**
- * Symmetric Encrypt
- *
- * @param inputBytes
- * Byte array you want to encrypt
- * @param passphrase
- * symmetric passhprase
- * @param callback
- * Callback where to return results
- */
- oneway void encrypt(in byte[] inputBytes, in String passphrase, in IExtendedApiCallback callback);
-
- /**
- * Generates self signed X509 certificate signed by OpenPGP private key (from app settings)
- *
- * @param subjAltNameURI
- * @param callback
- * Callback where to return results
- */
- oneway void selfSignedX509Cert(in String subjAltNameURI, in IExtendedApiCallback callback);
-
-} \ No newline at end of file
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/OpenPgpData.java b/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java
deleted file mode 100644
index 6615c2146..000000000
--- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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 android.net.Uri;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-
-public class OpenPgpData implements Parcelable {
- public static final int TYPE_STRING = 0;
- public static final int TYPE_BYTE_ARRAY = 1;
- public static final int TYPE_FILE_DESCRIPTOR = 2;
- public static final int TYPE_URI = 3;
-
- int type;
-
- String string;
- byte[] bytes = new byte[0];
- ParcelFileDescriptor fileDescriptor;
- Uri uri;
-
- public int getType() {
- return type;
- }
-
- public String getString() {
- return string;
- }
-
- public byte[] getBytes() {
- return bytes;
- }
-
- public ParcelFileDescriptor getFileDescriptor() {
- return fileDescriptor;
- }
-
- public Uri getUri() {
- return uri;
- }
-
- public OpenPgpData() {
-
- }
-
- /**
- * Not a real constructor. This can be used to define requested output type.
- *
- * @param type
- */
- public OpenPgpData(int type) {
- this.type = type;
- }
-
- public OpenPgpData(String string) {
- this.string = string;
- this.type = TYPE_STRING;
- }
-
- public OpenPgpData(byte[] bytes) {
- this.bytes = bytes;
- this.type = TYPE_BYTE_ARRAY;
- }
-
- public OpenPgpData(ParcelFileDescriptor fileDescriptor) {
- this.fileDescriptor = fileDescriptor;
- this.type = TYPE_FILE_DESCRIPTOR;
- }
-
- public OpenPgpData(Uri uri) {
- this.uri = uri;
- this.type = TYPE_URI;
- }
-
- public OpenPgpData(OpenPgpData b) {
- this.string = b.string;
- this.bytes = b.bytes;
- this.fileDescriptor = b.fileDescriptor;
- this.uri = b.uri;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(type);
- dest.writeString(string);
- dest.writeInt(bytes.length);
- dest.writeByteArray(bytes);
- dest.writeParcelable(fileDescriptor, 0);
- dest.writeParcelable(uri, 0);
- }
-
- public static final Creator<OpenPgpData> CREATOR = new Creator<OpenPgpData>() {
- public OpenPgpData createFromParcel(final Parcel source) {
- OpenPgpData vr = new OpenPgpData();
- vr.type = source.readInt();
- vr.string = source.readString();
- vr.bytes = new byte[source.readInt()];
- source.readByteArray(vr.bytes);
- vr.fileDescriptor = source.readParcelable(ParcelFileDescriptor.class.getClassLoader());
- vr.fileDescriptor = source.readParcelable(Uri.class.getClassLoader());
- return vr;
- }
-
- public OpenPgpData[] newArray(final int size) {
- return new OpenPgpData[size];
- }
- };
-
-}
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 <dominik@dominikschuermann.de>
- *
- * 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<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(intent, 0);
- if (!resInfo.isEmpty()) {
- return true;
- } else {
- return false;
- }
- }
-
-}
diff --git a/libraries/keychain-api-library/src/org/openintents/openpgp/IOpenPgpService.aidl b/libraries/keychain-api-library/src/org/openintents/openpgp/IOpenPgpService.aidl
new file mode 100644
index 000000000..578a7d4b5
--- /dev/null
+++ b/libraries/keychain-api-library/src/org/openintents/openpgp/IOpenPgpService.aidl
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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;
+
+interface IOpenPgpService {
+
+ /**
+ * General extras
+ * --------------
+ *
+ * Bundle params:
+ * int api_version (required)
+ * boolean ascii_armor (request ascii armor for ouput)
+ *
+ * returned Bundle:
+ * int result_code (0, 1, or 2 (see OpenPgpConstants))
+ * OpenPgpError error (if result_code == 0)
+ * Intent intent (if result_code == 2)
+ *
+ */
+
+ /**
+ * Sign only
+ *
+ * optional params:
+ * String passphrase (for key passphrase)
+ */
+ Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
+
+ /**
+ * Encrypt
+ *
+ * Bundle params:
+ * long[] key_ids
+ * or
+ * String[] user_ids (= emails of recipients) (if more than one key has this user_id, a PendingIntent is returned)
+ *
+ * optional params:
+ * String passphrase (for key passphrase)
+ */
+ Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
+
+ /**
+ * Sign and encrypt
+ *
+ * Bundle params:
+ * same as in encrypt()
+ */
+ 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.
+ *
+ * returned Bundle:
+ * OpenPgpSignatureResult signature_result
+ */
+ Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
+
+ /**
+ * Retrieves key ids based on given user ids (=emails)
+ *
+ * Bundle params:
+ * String[] user_ids
+ *
+ * returned Bundle:
+ * long[] key_ids
+ */
+ Bundle getKeyIds(in Bundle params);
+
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java b/libraries/keychain-api-library/src/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/libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpError.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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/OpenPgpSignatureResult.java b/libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpSignatureResult.java
index 829f8f8cf..16c79ca27 100644
--- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java
+++ b/libraries/keychain-api-library/src/org/openintents/openpgp/OpenPgpSignatureResult.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,14 +22,14 @@ import android.os.Parcelable;
public class OpenPgpSignatureResult implements Parcelable {
// generic error on signature verification
public static final int SIGNATURE_ERROR = 0;
- // successfully verified signature, with trusted public key
- public static final int SIGNATURE_SUCCESS_TRUSTED = 1;
+ // successfully verified signature, with certified public key
+ public static final int SIGNATURE_SUCCESS_CERTIFIED = 1;
// no public key was found for this signature verification
// you can retrieve the key with
// getKeys(new String[] {String.valueOf(signatureResult.getKeyId)}, true, callback)
public static final int SIGNATURE_UNKNOWN_PUB_KEY = 2;
- // successfully verified signature, but with untrusted public key
- public static final int SIGNATURE_SUCCESS_UNTRUSTED = 3;
+ // successfully verified signature, but with certified public key
+ public static final int SIGNATURE_SUCCESS_UNCERTIFIED = 3;
int status;
boolean signatureOnly;
diff --git a/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpApi.java b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpApi.java
new file mode 100644
index 000000000..f121c345d
--- /dev/null
+++ b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpApi.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import org.openintents.openpgp.IOpenPgpService;
+import org.openintents.openpgp.OpenPgpError;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class OpenPgpApi {
+
+ IOpenPgpService mService;
+ Context mContext;
+
+ 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;
+ private static final int OPERATION_GET_KEY_IDS = 4;
+
+ public OpenPgpApi(Context context, IOpenPgpService service) {
+ this.mContext = context;
+ 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 Bundle getKeyIds(Bundle params) {
+ return executeApi(OPERATION_GET_KEY_IDS, params, null, null);
+ }
+
+ public interface IOpenPgpCallback {
+ void onReturn(final Bundle result);
+ }
+
+ private class OpenPgpAsyncTask extends AsyncTask<Void, Integer, Bundle> {
+ 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 {
+ params.putInt(OpenPgpConstants.PARAMS_API_VERSION, OpenPgpConstants.API_VERSION);
+
+ Bundle result = null;
+
+ if (operationId == OPERATION_GET_KEY_IDS) {
+ result = mService.getKeyIds(params);
+ return result;
+ } else {
+ // 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
+ 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();
+
+ // set class loader to current context to allow unparcelling
+ // of OpenPgpError and OpenPgpSignatureResult
+ // http://stackoverflow.com/a/3806769
+ result.setClassLoader(mContext.getClassLoader());
+
+ return result;
+ }
+ } 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,
+ new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage()));
+ return result;
+ }
+ }
+
+
+}
diff --git a/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpConstants.java b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpConstants.java
new file mode 100644
index 000000000..263b42aaa
--- /dev/null
+++ b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpConstants.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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_USER_IDS = "user_ids";
+ public static final String PARAMS_KEY_IDS = "key_ids";
+ // optional parameter:
+ public static final String PARAMS_PASSPHRASE = "passphrase";
+
+ /* Service Bundle returns */
+ 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;
+ // executeServiceMethod intent and do it again with params from intent
+ public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2;
+
+ /* PendingIntent returns */
+ public static final String PI_RESULT_PARAMS = "params";
+
+}
diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpListPreference.java
index 4ddd97485..034186a3a 100644
--- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java
+++ b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpListPreference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,18 +14,14 @@
* limitations under the License.
*/
-package org.openintents.openpgp;
-
-import java.util.ArrayList;
-import java.util.List;
+package org.openintents.openpgp.util;
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.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.preference.DialogPreference;
import android.util.AttributeSet;
@@ -35,33 +31,21 @@ import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.sufficientlysecure.keychain.api.R;
+
+/**
+ * Does not extend ListPreference, but is very similar to it!
+ * http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/preference/ListPreference.java/?v=source
+ */
public class OpenPgpListPreference extends DialogPreference {
- ArrayList<OpenPgpProviderEntry> mProviderList = new ArrayList<OpenPgpProviderEntry>();
+ private ArrayList<OpenPgpProviderEntry> mProviderList = new ArrayList<OpenPgpProviderEntry>();
private String mSelectedPackage;
public OpenPgpListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
-
- List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(
- new Intent(OpenPgpConstants.SERVICE_INTENT), PackageManager.GET_META_DATA);
- if (!resInfo.isEmpty()) {
- for (ResolveInfo resolveInfo : resInfo) {
- if (resolveInfo.serviceInfo == null)
- continue;
-
- String packageName = resolveInfo.serviceInfo.packageName;
- String simpleName = String.valueOf(resolveInfo.serviceInfo.loadLabel(context
- .getPackageManager()));
- 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) {
@@ -69,20 +53,42 @@ public class OpenPgpListPreference extends DialogPreference {
}
/**
- * Can be used to add "no selection"
- *
+ * Public method to add new entries for legacy applications
+ *
* @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));
+ public void addProvider(int position, String packageName, String simpleName, Drawable icon) {
+ mProviderList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon));
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
+
+ // get providers
+ mProviderList.clear();
+ Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT);
+ List<ResolveInfo> resInfo = getContext().getPackageManager().queryIntentServices(intent, 0);
+ if (!resInfo.isEmpty()) {
+ for (ResolveInfo resolveInfo : resInfo) {
+ if (resolveInfo.serviceInfo == null)
+ continue;
+
+ String packageName = resolveInfo.serviceInfo.packageName;
+ String simpleName = String.valueOf(resolveInfo.serviceInfo.loadLabel(getContext()
+ .getPackageManager()));
+ Drawable icon = resolveInfo.serviceInfo.loadIcon(getContext().getPackageManager());
+
+ mProviderList.add(new OpenPgpProviderEntry(packageName, simpleName, icon));
+ }
+ }
+
+ // add "none"-entry
+ mProviderList.add(0, new OpenPgpProviderEntry("",
+ getContext().getString(R.string.openpgp_list_preference_none),
+ getContext().getResources().getDrawable(R.drawable.ic_action_cancel_launchersize)));
+
// Init ArrayAdapter with OpenPGP Providers
ListAdapter adapter = new ArrayAdapter<OpenPgpProviderEntry>(getContext(),
android.R.layout.select_dialog_singlechoice, android.R.id.text1, mProviderList) {
@@ -99,15 +105,6 @@ public class OpenPgpListPreference extends DialogPreference {
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;
}
};
@@ -169,6 +166,16 @@ public class OpenPgpListPreference extends DialogPreference {
return getEntryByValue(mSelectedPackage);
}
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return a.getString(index);
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setValue(restoreValue ? getPersistedString(mSelectedPackage) : (String) defaultValue);
+ }
+
public String getEntryByValue(String packageName) {
for (OpenPgpProviderEntry app : mProviderList) {
if (app.packageName.equals(packageName)) {
@@ -183,14 +190,11 @@ public class OpenPgpListPreference extends DialogPreference {
private String packageName;
private String simpleName;
private Drawable icon;
- private int apiVersion;
- public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon,
- int apiVersion) {
+ public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon) {
this.packageName = packageName;
this.simpleName = simpleName;
this.icon = icon;
- this.apiVersion = apiVersion;
}
@Override
diff --git a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpServiceConnection.java
index f7ba06aaf..8e8812faa 100644
--- a/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java
+++ b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpServiceConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.openintents.openpgp;
+package org.openintents.openpgp.util;
import org.openintents.openpgp.IOpenPgpService;
@@ -61,11 +61,12 @@ public class OpenPgpServiceConnection {
/**
* If not already bound, bind!
- *
+ *
* @return
*/
public boolean bindToService() {
- if (mService == null && !mBound) { // if not already connected
+ // if not already connected
+ if (mService == null && !mBound) {
try {
Log.d(OpenPgpConstants.TAG, "not bound yet");
diff --git a/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpUtils.java b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpUtils.java
new file mode 100644
index 000000000..ffecaceba
--- /dev/null
+++ b/libraries/keychain-api-library/src/org/openintents/openpgp/util/OpenPgpUtils.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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.Matcher;
+import java.util.regex.Pattern;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+
+public class OpenPgpUtils {
+
+ public static final Pattern PGP_MESSAGE = Pattern.compile(
+ ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
+ Pattern.DOTALL);
+
+ public static final Pattern PGP_SIGNED_MESSAGE = Pattern.compile(
+ ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
+ Pattern.DOTALL);
+
+ public static final int PARSE_RESULT_NO_PGP = -1;
+ public static final int PARSE_RESULT_MESSAGE = 0;
+ public static final int PARSE_RESULT_SIGNED_MESSAGE = 1;
+
+ public static int parseMessage(String message) {
+ Matcher matcherSigned = PGP_SIGNED_MESSAGE.matcher(message);
+ Matcher matcherMessage = PGP_MESSAGE.matcher(message);
+
+ if (matcherMessage.matches()) {
+ return PARSE_RESULT_MESSAGE;
+ } else if (matcherSigned.matches()) {
+ return PARSE_RESULT_SIGNED_MESSAGE;
+ } else {
+ return PARSE_RESULT_NO_PGP;
+ }
+ }
+
+ public static boolean isAvailable(Context context) {
+ Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT);
+ List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(intent, 0);
+ if (!resInfo.isEmpty()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/libraries/keychain-api-library/src/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java b/libraries/keychain-api-library/src/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java
new file mode 100644
index 000000000..75d4b8c18
--- /dev/null
+++ b/libraries/keychain-api-library/src/org/openintents/openpgp/util/ParcelFileDescriptorUtil.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * 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) {
+ Log.e(OpenPgpConstants.TAG, "TransferThread" + getId(), e);
+ }
+ try {
+ mOut.close();
+ } catch (IOException e) {
+ Log.e(OpenPgpConstants.TAG, "TransferThread" + getId(), e);
+ }
+ }
+ if (mListener != null) {
+ Log.d(OpenPgpConstants.TAG, "TransferThread " + getId() + " finished!");
+ mListener.onThreadFinished(this);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/libraries/keychain-api-library/src/org/sufficientlysecure/keychain/api/OpenKeychainIntents.java b/libraries/keychain-api-library/src/org/sufficientlysecure/keychain/api/OpenKeychainIntents.java
new file mode 100644
index 000000000..15aceb534
--- /dev/null
+++ b/libraries/keychain-api-library/src/org/sufficientlysecure/keychain/api/OpenKeychainIntents.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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.sufficientlysecure.keychain.api;
+
+public class OpenKeychainIntents {
+
+ public static final String ENCRYPT = "org.sufficientlysecure.keychain.action.ENCRYPT";
+ public static final String ENCRYPT_EXTRA_TEXT = "text"; // String
+ public static final String ENCRYPT_ASCII_ARMOR = "ascii_armor"; // boolean
+
+ public static final String DECRYPT = "org.sufficientlysecure.keychain.action.DECRYPT";
+ public static final String DECRYPT_EXTRA_TEXT = "text"; // String
+
+ public static final String IMPORT_KEY = "org.sufficientlysecure.keychain.action.IMPORT_KEY";
+ public static final String IMPORT_KEY_EXTRA_KEY_BYTES = "key_bytes"; // byte[]
+
+ public static final String IMPORT_KEY_FROM_KEYSERVER = "org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_KEYSERVER";
+ public static final String IMPORT_KEY_FROM_KEYSERVER_QUERY = "query"; // String
+ public static final String IMPORT_KEY_FROM_KEYSERVER_FINGERPRINT = "fingerprint"; // String
+
+ public static final String IMPORT_KEY_FROM_QR_CODE = "org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_QR_CODE";
+
+}