From 754b2a6cb15a6af61150cd4b1ce472bebd4fec22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 9 Feb 2014 19:22:14 +0100 Subject: Restructuring for new API library --- .../org/openintents/openpgp/OpenPgpConstants.java | 10 + .../java/org/openintents/openpgp/OpenPgpData.java | 127 +++++++++++++ .../java/org/openintents/openpgp/OpenPgpError.java | 81 +++++++++ .../org/openintents/openpgp/OpenPgpHelper.java | 52 ++++++ .../openintents/openpgp/OpenPgpListPreference.java | 201 +++++++++++++++++++++ .../openpgp/OpenPgpServiceConnection.java | 93 ++++++++++ .../openpgp/OpenPgpSignatureResult.java | 110 +++++++++++ 7 files changed, 674 insertions(+) create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java create mode 100644 OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java (limited to 'OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org') 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 new file mode 100644 index 000000000..b1ca1bfe6 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpConstants.java @@ -0,0 +1,10 @@ +package org.openintents.openpgp; + +public class OpenPgpConstants { + + public static final String TAG = "OpenPgp API"; + + public static final int REQUIRED_API_VERSION = 1; + public static final String SERVICE_INTENT = "org.openintents.openpgp.IOpenPgpService"; + +} diff --git a/OpenPGP-Keychain-API/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 new file mode 100644 index 000000000..6615c2146 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpData.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp; + +import 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 CREATOR = new Creator() { + 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/OpenPgpError.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java new file mode 100644 index 000000000..f108d3169 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpError.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp; + +import android.os.Parcel; +import android.os.Parcelable; + +public class OpenPgpError implements Parcelable { + 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; + + int errorId; + String message; + + public OpenPgpError() { + } + + public OpenPgpError(int errorId, String message) { + this.errorId = errorId; + this.message = message; + } + + public OpenPgpError(OpenPgpError b) { + this.errorId = b.errorId; + this.message = b.message; + } + + public int getErrorId() { + return errorId; + } + + public void setErrorId(int errorId) { + this.errorId = errorId; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(errorId); + dest.writeString(message); + } + + public static final Creator CREATOR = new Creator() { + public OpenPgpError createFromParcel(final Parcel source) { + OpenPgpError error = new OpenPgpError(); + error.errorId = source.readInt(); + error.message = source.readString(); + return error; + } + + public OpenPgpError[] newArray(final int size) { + return new OpenPgpError[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 new file mode 100644 index 000000000..7305c47ce --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpHelper.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp; + +import java.util.List; +import java.util.regex.Pattern; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; + +public class OpenPgpHelper { + private Context context; + + public static Pattern PGP_MESSAGE = Pattern.compile( + ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); + + public static Pattern PGP_SIGNED_MESSAGE = Pattern + .compile( + ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*", + Pattern.DOTALL); + + public OpenPgpHelper(Context context) { + super(); + this.context = context; + } + + public boolean isAvailable() { + Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT); + List resInfo = context.getPackageManager().queryIntentServices(intent, 0); + if (!resInfo.isEmpty()) { + return true; + } else { + return false; + } + } + +} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java new file mode 100644 index 000000000..4ddd97485 --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpListPreference.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp; + +import java.util.ArrayList; +import java.util.List; + +import android.app.AlertDialog.Builder; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.graphics.drawable.Drawable; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.TextView; + +public class OpenPgpListPreference extends DialogPreference { + ArrayList mProviderList = new ArrayList(); + private String mSelectedPackage; + + public OpenPgpListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + List resInfo = context.getPackageManager().queryIntentServices( + new Intent(OpenPgpConstants.SERVICE_INTENT), PackageManager.GET_META_DATA); + if (!resInfo.isEmpty()) { + for (ResolveInfo resolveInfo : resInfo) { + if (resolveInfo.serviceInfo == null) + continue; + + String packageName = resolveInfo.serviceInfo.packageName; + String simpleName = String.valueOf(resolveInfo.serviceInfo.loadLabel(context + .getPackageManager())); + Drawable icon = resolveInfo.serviceInfo.loadIcon(context.getPackageManager()); + + // get api version + ServiceInfo si = resolveInfo.serviceInfo; + int apiVersion = si.metaData.getInt("api_version"); + + mProviderList.add(new OpenPgpProviderEntry(packageName, simpleName, icon, + apiVersion)); + } + } + } + + public OpenPgpListPreference(Context context) { + this(context, null); + } + + /** + * Can be used to add "no selection" + * + * @param packageName + * @param simpleName + * @param icon + */ + public void addProvider(int position, String packageName, String simpleName, Drawable icon, + int apiVersion) { + mProviderList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon, + apiVersion)); + } + + @Override + protected void onPrepareDialogBuilder(Builder builder) { + // Init ArrayAdapter with OpenPGP Providers + ListAdapter adapter = new ArrayAdapter(getContext(), + android.R.layout.select_dialog_singlechoice, android.R.id.text1, mProviderList) { + public View getView(int position, View convertView, ViewGroup parent) { + // User super class to create the View + View v = super.getView(position, convertView, parent); + TextView tv = (TextView) v.findViewById(android.R.id.text1); + + // Put the image on the TextView + tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon, null, + null, null); + + // Add margin between image and text (support various screen densities) + int dp10 = (int) (10 * getContext().getResources().getDisplayMetrics().density + 0.5f); + tv.setCompoundDrawablePadding(dp10); + + // disable if it has the wrong api_version + if (mProviderList.get(position).apiVersion == OpenPgpConstants.REQUIRED_API_VERSION) { + tv.setEnabled(true); + } else { + tv.setEnabled(false); + tv.setText(tv.getText() + " (API v" + mProviderList.get(position).apiVersion + + ", needs v" + OpenPgpConstants.REQUIRED_API_VERSION + ")"); + } + + return v; + } + }; + + builder.setSingleChoiceItems(adapter, getIndexOfProviderList(getValue()), + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + mSelectedPackage = mProviderList.get(which).packageName; + + /* + * Clicking on an item simulates the positive button click, and dismisses + * the dialog. + */ + OpenPgpListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE); + dialog.dismiss(); + } + }); + + /* + * The typical interaction for list-based dialogs is to have click-on-an-item dismiss the + * dialog instead of the user having to press 'Ok'. + */ + builder.setPositiveButton(null, null); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + + if (positiveResult && (mSelectedPackage != null)) { + if (callChangeListener(mSelectedPackage)) { + setValue(mSelectedPackage); + } + } + } + + private int getIndexOfProviderList(String packageName) { + for (OpenPgpProviderEntry app : mProviderList) { + if (app.packageName.equals(packageName)) { + return mProviderList.indexOf(app); + } + } + + return -1; + } + + public void setValue(String packageName) { + mSelectedPackage = packageName; + persistString(packageName); + } + + public String getValue() { + return mSelectedPackage; + } + + public String getEntry() { + return getEntryByValue(mSelectedPackage); + } + + public String getEntryByValue(String packageName) { + for (OpenPgpProviderEntry app : mProviderList) { + if (app.packageName.equals(packageName)) { + return app.simpleName; + } + } + + return null; + } + + private static class OpenPgpProviderEntry { + private String packageName; + private String simpleName; + private Drawable icon; + private int apiVersion; + + public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon, + int apiVersion) { + this.packageName = packageName; + this.simpleName = simpleName; + this.icon = icon; + this.apiVersion = apiVersion; + } + + @Override + public String toString() { + return simpleName; + } + } +} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java new file mode 100644 index 000000000..f7ba06aaf --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpServiceConnection.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp; + +import org.openintents.openpgp.IOpenPgpService; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +public class OpenPgpServiceConnection { + private Context mApplicationContext; + + private IOpenPgpService mService; + private boolean mBound; + private String mCryptoProviderPackageName; + + public OpenPgpServiceConnection(Context context, String cryptoProviderPackageName) { + this.mApplicationContext = context.getApplicationContext(); + this.mCryptoProviderPackageName = cryptoProviderPackageName; + } + + public IOpenPgpService getService() { + return mService; + } + + public boolean isBound() { + return mBound; + } + + private ServiceConnection mCryptoServiceConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + mService = IOpenPgpService.Stub.asInterface(service); + Log.d(OpenPgpConstants.TAG, "connected to service"); + mBound = true; + } + + public void onServiceDisconnected(ComponentName name) { + mService = null; + Log.d(OpenPgpConstants.TAG, "disconnected from service"); + mBound = false; + } + }; + + /** + * If not already bound, bind! + * + * @return + */ + public boolean bindToService() { + if (mService == null && !mBound) { // if not already connected + try { + Log.d(OpenPgpConstants.TAG, "not bound yet"); + + Intent serviceIntent = new Intent(); + serviceIntent.setAction(IOpenPgpService.class.getName()); + serviceIntent.setPackage(mCryptoProviderPackageName); + mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection, + Context.BIND_AUTO_CREATE); + + return true; + } catch (Exception e) { + Log.d(OpenPgpConstants.TAG, "Exception on binding", e); + return false; + } + } else { + Log.d(OpenPgpConstants.TAG, "already bound"); + return true; + } + } + + public void unbindFromService() { + mApplicationContext.unbindService(mCryptoServiceConnection); + } + +} diff --git a/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java new file mode 100644 index 000000000..829f8f8cf --- /dev/null +++ b/OpenPGP-Keychain-API/libraries/keychain-api-library/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.openpgp; + +import android.os.Parcel; +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; + // 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; + + int status; + boolean signatureOnly; + String userId; + long keyId; + + public int getStatus() { + return status; + } + + public boolean isSignatureOnly() { + return signatureOnly; + } + + public String getUserId() { + return userId; + } + + public long getKeyId() { + return keyId; + } + + public OpenPgpSignatureResult() { + + } + + public OpenPgpSignatureResult(int signatureStatus, String signatureUserId, + boolean signatureOnly, long keyId) { + this.status = signatureStatus; + this.signatureOnly = signatureOnly; + this.userId = signatureUserId; + this.keyId = keyId; + } + + public OpenPgpSignatureResult(OpenPgpSignatureResult b) { + this.status = b.status; + this.userId = b.userId; + this.signatureOnly = b.signatureOnly; + this.keyId = b.keyId; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(status); + dest.writeByte((byte) (signatureOnly ? 1 : 0)); + dest.writeString(userId); + dest.writeLong(keyId); + } + + public static final Creator CREATOR = new Creator() { + public OpenPgpSignatureResult createFromParcel(final Parcel source) { + OpenPgpSignatureResult vr = new OpenPgpSignatureResult(); + vr.status = source.readInt(); + vr.signatureOnly = source.readByte() == 1; + vr.userId = source.readString(); + vr.keyId = source.readLong(); + return vr; + } + + public OpenPgpSignatureResult[] newArray(final int size) { + return new OpenPgpSignatureResult[size]; + } + }; + + @Override + public String toString() { + String out = new String(); + out += "\nstatus: " + status; + out += "\nuserId: " + userId; + out += "\nsignatureOnly: " + signatureOnly; + out += "\nkeyId: " + keyId; + return out; + } + +} -- cgit v1.2.3