diff --git a/README.md b/README.md index 5d0a8f733..625da5b44 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,12 @@ This is a fork of Android Privacy Guard (APG) named APG+ -I will try to reintegrate the various forks and build a new stable version, which can be released to the market. +I will try to reintegrate the various forks and build a new stable version, which can be released to Google Play Store. # Contribute Fork APG+ and do a merge request. I will merge your changes back into the main project. -# Build using Eclipse - -1. New -> Android Project -> Create project from existing source, choose com_actionbarsherlock -2. New -> Android Project -> Create project from existing source, choose org_apg -3. Add com_actionbarsherlock as Android Lib (Properties of org_apg -> Android -> Library -> add) -4. Optional (As of Android Tools r17 the libraries are automatically added from the libs folder): Add Java libs (Properties of org_apg -> Java Build Path -> Libraries -> add all libraries from libs folder in org_apg) -5. Now APG+ can be build - # Build using Ant ## Command Line @@ -28,7 +20,15 @@ Fork APG+ and do a merge request. I will merge your changes back into the main p sdk.dir=/opt/android-sdk -2. execute "ant release" +2. execute "ant release" + +# Build using Eclipse + +1. New -> Android Project -> Create project from existing source, choose com_actionbarsherlock +2. New -> Android Project -> Create project from existing source, choose org_apg +3. Add com_actionbarsherlock as Android Lib (Properties of org_apg -> Android -> Library -> add) +4. Optional (As of Android Tools r17 the libraries are automatically added from the libs folder): Add Java libs (Properties of org_apg -> Java Build Path -> Libraries -> add all libraries from libs folder in org_apg) +5. Now APG+ can be build # Libraries @@ -39,7 +39,7 @@ The Libraries are provided in the git repository. * android-support-v4.jar: Compatibility Lib * barcodescanner-android-integration-supportv4.jar: Barcode Scanner Integration -# Build XZing Integration Library +## Build Barcode Scanner Integration 1. Checkout their SVN (see http://code.google.com/p/zxing/source/checkout) 2. Change android-home variable in "build.properties" in the main directory to point to your Android SDK @@ -49,11 +49,13 @@ The Libraries are provided in the git repository. On error see: http://code.google.com/p/zxing/issues/detail?id=1207 -# Build Spongy Castle +## Build Spongy Castle see https://github.com/rtyley/spongycastle -# Generate pressed dashboard icons +# Notes -1. Open svg in Inkscape +## Generate pressed dashboard icons + +1. Open svg file in Inkscape 2. Extensions -> Color -> darker (2 times!) \ No newline at end of file diff --git a/org_apg/AndroidManifest.xml b/org_apg/AndroidManifest.xml index 797f87fab..728b49157 100644 --- a/org_apg/AndroidManifest.xml +++ b/org_apg/AndroidManifest.xml @@ -1,5 +1,4 @@ - + android:theme="@style/Theme.Sherlock.Light.ForceOverflow" android:name="ApgApplication"> - + @@ -247,7 +246,7 @@ android:authorities="org.thialfihar.android.apg.provider" android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" /> diff --git a/org_apg/src/org/thialfihar/android/apg/Apg.java b/org_apg/src/org/thialfihar/android/apg/Apg.java index 6d966324a..72fc7b49d 100644 --- a/org_apg/src/org/thialfihar/android/apg/Apg.java +++ b/org_apg/src/org/thialfihar/android/apg/Apg.java @@ -64,6 +64,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; import org.thialfihar.android.apg.Id.return_value; import org.thialfihar.android.apg.KeyServer.AddKeyException; +import org.thialfihar.android.apg.passphrase.CachedPassPhrase; import org.thialfihar.android.apg.provider.DataProvider; import org.thialfihar.android.apg.provider.Database; import org.thialfihar.android.apg.provider.KeyRings; @@ -2289,7 +2290,7 @@ public class Apg { return result; } - static long getLengthOfStream(InputStream in) throws IOException { + public static long getLengthOfStream(InputStream in) throws IOException { long size = 0; long n = 0; byte dummy[] = new byte[0x10000]; diff --git a/org_apg/src/org/thialfihar/android/apg/ApgApplication.java b/org_apg/src/org/thialfihar/android/apg/ApgApplication.java new file mode 100644 index 000000000..27b8b82cf --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/ApgApplication.java @@ -0,0 +1,18 @@ +package org.thialfihar.android.apg; + +import org.thialfihar.android.apg.passphrase.PassphraseCacheService; + +import android.app.Application; +import android.content.Intent; + +public class ApgApplication extends Application { + + @Override + public void onCreate() { + super.onCreate(); + + /** Start passphrase cache service */ + PassphraseCacheService.startCacheService(this); + } + +} diff --git a/org_apg/src/org/thialfihar/android/apg/DataDestination.java b/org_apg/src/org/thialfihar/android/apg/DataDestination.java index 2ab530619..6fa60889c 100644 --- a/org_apg/src/org/thialfihar/android/apg/DataDestination.java +++ b/org_apg/src/org/thialfihar/android/apg/DataDestination.java @@ -19,6 +19,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.Serializable; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Apg.GeneralException; @@ -26,7 +27,10 @@ import org.thialfihar.android.apg.Apg.GeneralException; import android.content.Context; import android.os.Environment; -public class DataDestination { +public class DataDestination implements Serializable { + + private static final long serialVersionUID = -6478075911319320498L; + private String mStreamFilename; private String mFilename; private int mMode = Id.mode.undefined; diff --git a/org_apg/src/org/thialfihar/android/apg/DataSource.java b/org_apg/src/org/thialfihar/android/apg/DataSource.java index 637304012..503e0867f 100644 --- a/org_apg/src/org/thialfihar/android/apg/DataSource.java +++ b/org_apg/src/org/thialfihar/android/apg/DataSource.java @@ -20,6 +20,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.Serializable; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Apg.GeneralException; @@ -28,7 +29,10 @@ import android.content.Context; import android.net.Uri; import android.os.Environment; -public class DataSource { +public class DataSource implements Serializable { + + private static final long serialVersionUID = 2377217399907415255L; + private Uri mContentUri = null; private String mText = null; private byte[] mData = null; @@ -51,6 +55,10 @@ public class DataSource { } } + public Uri getUri() { + return mContentUri; + } + public void setText(String text) { mText = text; mData = null; @@ -71,6 +79,17 @@ public class DataSource { return mData != null || mContentUri != null; } + public byte[] getBytes() { + byte[] bytes = null; + if (mData != null) { + bytes = mData; + } else { + bytes = mText.getBytes(); + } + + return bytes; + } + public InputData getInputData(Context context, boolean withSize) throws GeneralException, FileNotFoundException, IOException { InputStream in = null; diff --git a/org_apg/src/org/thialfihar/android/apg/Preferences.java b/org_apg/src/org/thialfihar/android/apg/Preferences.java index ea6a36368..a550fed77 100644 --- a/org_apg/src/org/thialfihar/android/apg/Preferences.java +++ b/org_apg/src/org/thialfihar/android/apg/Preferences.java @@ -22,6 +22,10 @@ import android.content.SharedPreferences; import java.util.Vector; +/** + * Singelton Implementation of a Preference Helper + * + */ public class Preferences { private static Preferences mPreferences; private SharedPreferences mSharedPreferences; diff --git a/org_apg/src/org/thialfihar/android/apg/AskForSecretKeyPassPhrase.java b/org_apg/src/org/thialfihar/android/apg/passphrase/AskForPassphrase.java similarity index 92% rename from org_apg/src/org/thialfihar/android/apg/AskForSecretKeyPassPhrase.java rename to org_apg/src/org/thialfihar/android/apg/passphrase/AskForPassphrase.java index 35198d7b4..27cb0a41e 100644 --- a/org_apg/src/org/thialfihar/android/apg/AskForSecretKeyPassPhrase.java +++ b/org_apg/src/org/thialfihar/android/apg/passphrase/AskForPassphrase.java @@ -14,12 +14,14 @@ * limitations under the License. */ -package org.thialfihar.android.apg; +package org.thialfihar.android.apg.passphrase; import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPSecretKey; +import org.thialfihar.android.apg.Apg; +import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; import android.app.Activity; @@ -35,7 +37,7 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; -public class AskForSecretKeyPassPhrase { +public class AskForPassphrase { public static interface PassPhraseCallbackInterface { void passPhraseCallback(long keyId, String passPhrase); } @@ -107,6 +109,10 @@ public class AskForSecretKeyPassPhrase { } else { keyId = Id.key.symmetric; } + + // cache again + Apg.setCachedPassPhrase(keyId, passPhrase); + // return by callback cb.passPhraseCallback(keyId, passPhrase); } }); @@ -126,6 +132,9 @@ public class AskForSecretKeyPassPhrase { if (testKey != null) { Log.d("APG", "Key has no passphrase!"); + // cache null + Apg.setCachedPassPhrase(secretKey.getKeyID(), null); + // return by callback cb.passPhraseCallback(secretKey.getKeyID(), null); return null; diff --git a/org_apg/src/org/thialfihar/android/apg/CachedPassPhrase.java b/org_apg/src/org/thialfihar/android/apg/passphrase/CachedPassPhrase.java similarity index 97% rename from org_apg/src/org/thialfihar/android/apg/CachedPassPhrase.java rename to org_apg/src/org/thialfihar/android/apg/passphrase/CachedPassPhrase.java index 85fcdd201..08696c6eb 100644 --- a/org_apg/src/org/thialfihar/android/apg/CachedPassPhrase.java +++ b/org_apg/src/org/thialfihar/android/apg/passphrase/CachedPassPhrase.java @@ -12,7 +12,7 @@ * limitations under the License. */ -package org.thialfihar.android.apg; +package org.thialfihar.android.apg.passphrase; public class CachedPassPhrase { public final long timestamp; diff --git a/org_apg/src/org/thialfihar/android/apg/service/PassphraseCacheService.java b/org_apg/src/org/thialfihar/android/apg/passphrase/PassphraseCacheService.java similarity index 86% rename from org_apg/src/org/thialfihar/android/apg/service/PassphraseCacheService.java rename to org_apg/src/org/thialfihar/android/apg/passphrase/PassphraseCacheService.java index f8b5959ee..9ef6eedb8 100644 --- a/org_apg/src/org/thialfihar/android/apg/service/PassphraseCacheService.java +++ b/org_apg/src/org/thialfihar/android/apg/passphrase/PassphraseCacheService.java @@ -12,11 +12,13 @@ * limitations under the License. */ -package org.thialfihar.android.apg.service; +package org.thialfihar.android.apg.passphrase; import org.thialfihar.android.apg.Apg; +import org.thialfihar.android.apg.Preferences; import android.app.Service; +import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.Handler; @@ -27,6 +29,12 @@ public class PassphraseCacheService extends Service { public static final String EXTRA_TTL = "ttl"; + public static void startCacheService(Context context) { + Intent intent = new Intent(context, PassphraseCacheService.class); + intent.putExtra(PassphraseCacheService.EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl()); + context.startService(intent); + } + private int mPassPhraseCacheTtl = 15; private Handler mCacheHandler = new Handler(); private Runnable mCacheTask = new Runnable() { diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ApgServiceBlobDatabase.java b/org_apg/src/org/thialfihar/android/apg/provider/blob/ApgServiceBlobDatabase.java similarity index 74% rename from org_apg/src/org/thialfihar/android/apg/provider/ApgServiceBlobDatabase.java rename to org_apg/src/org/thialfihar/android/apg/provider/blob/ApgServiceBlobDatabase.java index 509dfe8b4..5122f9da1 100644 --- a/org_apg/src/org/thialfihar/android/apg/provider/ApgServiceBlobDatabase.java +++ b/org_apg/src/org/thialfihar/android/apg/provider/blob/ApgServiceBlobDatabase.java @@ -12,7 +12,7 @@ * limitations under the License. */ -package org.thialfihar.android.apg.provider; +package org.thialfihar.android.apg.provider.blob; import org.thialfihar.android.apg.service.ApgService2; @@ -26,43 +26,47 @@ import android.net.Uri; import android.util.Log; public class ApgServiceBlobDatabase extends SQLiteOpenHelper { - + private static final String TAG = "ApgServiceBlobDatabase"; private static final int VERSION = 1; private static final String NAME = "apg_service_blob_data"; private static final String TABLE = "data"; - + public ApgServiceBlobDatabase(Context context) { super(context, NAME, null, VERSION); - if(ApgService2.LOCAL_LOGD) Log.d(TAG, "constructor called"); + if (ApgService2.LOCAL_LOGD) + Log.d(TAG, "constructor called"); } @Override public void onCreate(SQLiteDatabase db) { - if(ApgService2.LOCAL_LOGD) Log.d(TAG, "onCreate() called"); - db.execSQL("create table " + TABLE + " ( _id integer primary key autoincrement," + - "key text not null)"); + if (ApgService2.LOCAL_LOGD) + Log.d(TAG, "onCreate() called"); + db.execSQL("create table " + TABLE + " ( _id integer primary key autoincrement," + + "key text not null)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if(ApgService2.LOCAL_LOGD) Log.d(TAG, "onUpgrade() called"); + if (ApgService2.LOCAL_LOGD) + Log.d(TAG, "onUpgrade() called"); // no upgrade necessary yet } - + public Uri insert(ContentValues vals) { - if(ApgService2.LOCAL_LOGD) Log.d(TAG, "insert() called"); + if (ApgService2.LOCAL_LOGD) + Log.d(TAG, "insert() called"); SQLiteDatabase db = this.getWritableDatabase(); long newId = db.insert(TABLE, null, vals); return ContentUris.withAppendedId(ApgServiceBlobProvider.CONTENT_URI, newId); } - + public Cursor query(String id, String key) { - if(ApgService2.LOCAL_LOGD) Log.d(TAG, "query() called"); + if (ApgService2.LOCAL_LOGD) + Log.d(TAG, "query() called"); SQLiteDatabase db = this.getReadableDatabase(); - return db.query(TABLE, new String[] {"_id"}, - "_id = ? and key = ?", new String[] {id, key}, - null, null, null); + return db.query(TABLE, new String[] { "_id" }, "_id = ? and key = ?", new String[] { id, + key }, null, null, null); } } diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ApgServiceBlobProvider.java b/org_apg/src/org/thialfihar/android/apg/provider/blob/ApgServiceBlobProvider.java similarity index 99% rename from org_apg/src/org/thialfihar/android/apg/provider/ApgServiceBlobProvider.java rename to org_apg/src/org/thialfihar/android/apg/provider/blob/ApgServiceBlobProvider.java index d7bacab76..b16bc398e 100644 --- a/org_apg/src/org/thialfihar/android/apg/provider/ApgServiceBlobProvider.java +++ b/org_apg/src/org/thialfihar/android/apg/provider/blob/ApgServiceBlobProvider.java @@ -12,7 +12,7 @@ * limitations under the License. */ -package org.thialfihar.android.apg.provider; +package org.thialfihar.android.apg.provider.blob; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.service.ApgService2; diff --git a/org_apg/src/org/thialfihar/android/apg/provider/blob/BlobContract.java b/org_apg/src/org/thialfihar/android/apg/provider/blob/BlobContract.java new file mode 100644 index 000000000..dd9bd2069 --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/provider/blob/BlobContract.java @@ -0,0 +1,42 @@ +//package org.thialfihar.android.apg.provider.blob; +// +//import android.net.Uri; +//import android.provider.BaseColumns; +// +//public class BlobContract { +// +// interface BlobColumns { +// String DATA = "data"; +// } +// +// public static final String CONTENT_AUTHORITY = "org.thialfihar.android.apg"; +// +// private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY); +// +// public static final String PATH_BLOB = "blob"; +// +// public static class Blobs implements BlobColumns, BaseColumns { +// public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_BLOB) +// .build(); +// +// /** Use if multiple items get returned */ +// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.apg.blob"; +// +// /** Use if a single item is returned */ +// public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.apg.blob"; +// +// /** Default "ORDER BY" clause. */ +// public static final String DEFAULT_SORT = BaseColumns._ID + " ASC"; +// +// public static Uri buildUri(String id) { +// return CONTENT_URI.buildUpon().appendPath(id).build(); +// } +// +// public static String getId(Uri uri) { +// return uri.getLastPathSegment(); +// } +// } +// +// private BlobContract() { +// } +//} diff --git a/org_apg/src/org/thialfihar/android/apg/service/ApgHandler.java b/org_apg/src/org/thialfihar/android/apg/service/ApgHandler.java index 0557bd17a..3afd126c1 100644 --- a/org_apg/src/org/thialfihar/android/apg/service/ApgHandler.java +++ b/org_apg/src/org/thialfihar/android/apg/service/ApgHandler.java @@ -39,10 +39,6 @@ public class ApgHandler extends Handler { public static final String DATA_MESSAGE = "message"; public static final String DATA_MESSAGE_ID = "message_id"; - // possible data keys as result from service - public static final String RESULT_NEW_KEY = "new_key"; - public static final String RESULT_NEW_KEY2 = "new_key2"; - Activity mActivity; ProgressDialogFragment mProgressDialogFragment; diff --git a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java index ea28ffaa1..0268ff204 100644 --- a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java +++ b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java @@ -16,19 +16,37 @@ package org.thialfihar.android.apg.service; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Constants; +import org.thialfihar.android.apg.DataDestination; +import org.thialfihar.android.apg.DataSource; import org.thialfihar.android.apg.Id; +import org.thialfihar.android.apg.InputData; +import org.thialfihar.android.apg.Preferences; import org.thialfihar.android.apg.ProgressDialogUpdater; +import org.thialfihar.android.apg.R; +import org.thialfihar.android.apg.Apg.GeneralException; +import org.thialfihar.android.apg.provider.DataProvider; import org.thialfihar.android.apg.util.Utils; import android.app.IntentService; +import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; +import android.os.Environment; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; @@ -37,7 +55,7 @@ import android.util.Log; /** * This Service contains all important long lasting operations for APG. It receives Intents with * data from the activities or other apps, queues these intents, executes them, and stops itself - * doing it. + * after doing them. */ // TODO: ProgressDialogUpdater rework??? public class ApgService extends IntentService implements ProgressDialogUpdater { @@ -62,11 +80,40 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { public static final String PASSPHRASE = "passphrase"; public static final String MASTER_KEY = "master_key"; + // encrypt + public static final String SECRET_KEY_ID = "secret_key_id"; + // public static final String DATA_SOURCE = "data_source"; + // public static final String DATA_DESTINATION = "data_destination"; + public static final String USE_ASCII_AMOR = "use_ascii_amor"; + // public static final String ENCRYPTION_TARGET = "encryption_target"; + public static final String ENCRYPTION_KEYS_IDS = "encryption_keys_ids"; + public static final String SIGNATURE_KEY_ID = "signature_key_id"; + public static final String COMPRESSION_ID = "compression_id"; + public static final String GENERATE_SIGNATURE = "generate_signature"; + public static final String SIGN_ONLY = "sign_only"; + public static final String BYTES = "bytes"; + public static final String FILE_URI = "file_uri"; + public static final String OUTPUT_FILENAME = "output_filename"; + public static final String PROVIDER_URI = "provider_uri"; + // possible ints for EXTRA_ACTION public static final int ACTION_SAVE_KEYRING = 1; public static final int ACTION_GENERATE_KEY = 2; public static final int ACTION_GENERATE_DEFAULT_RSA_KEYS = 3; + public static final int ACTION_ENCRYPT_SIGN_BYTES = 4; + public static final int ACTION_ENCRYPT_SIGN_FILE = 5; + public static final int ACTION_ENCRYPT_SIGN_STREAM = 6; + + // possible data keys as result + public static final String RESULT_NEW_KEY = "new_key"; + public static final String RESULT_NEW_KEY2 = "new_key2"; + public static final String RESULT_SIGNATURE_DATA = "signatureData"; + public static final String RESULT_SIGNATURE_TEXT = "signatureText"; + public static final String RESULT_ENCRYPTED_MESSAGE = "encryptedMessage"; + public static final String RESULT_ENCRYPTED_DATA = "encryptedData"; + public static final String RESULT_URI = "resultUri"; + Messenger mMessenger; public ApgService() { @@ -82,26 +129,19 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); if (extras == null) { - Log.e(Constants.TAG, "Extra bundle is null!"); + Log.e(Constants.TAG, "Extras bundle is null!"); return; } - if (!extras.containsKey(EXTRA_MESSENGER)) { - Log.e(Constants.TAG, "Extra bundle must contain a messenger!"); + if (!(extras.containsKey(EXTRA_MESSENGER) || extras.containsKey(EXTRA_DATA) || extras + .containsKey(EXTRA_ACTION))) { + Log.e(Constants.TAG, + "Extra bundle must contain a messenger, a data bundle, and an action!"); return; } + mMessenger = (Messenger) extras.get(EXTRA_MESSENGER); - - if (!extras.containsKey(EXTRA_DATA)) { - Log.e(Constants.TAG, "Extra bundle must contain data bundle!"); - return; - } Bundle data = extras.getBundle(EXTRA_DATA); - - if (!extras.containsKey(EXTRA_ACTION)) { - Log.e(Constants.TAG, "Extra bundle must contain a action!"); - return; - } int action = extras.getInt(EXTRA_ACTION); // execute action from extra bundle @@ -155,9 +195,8 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // Output Bundle resultData = new Bundle(); - resultData.putByteArray(ApgHandler.RESULT_NEW_KEY, - Utils.PGPSecretKeyRingToBytes(newKeyRing)); - sendMessageToHandler(ApgHandler.MESSAGE_OKAY, null, resultData); + resultData.putByteArray(RESULT_NEW_KEY, Utils.PGPSecretKeyRingToBytes(newKeyRing)); + sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData); } catch (Exception e) { sendErrorToHandler(e); } @@ -178,13 +217,263 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // Output Bundle resultData = new Bundle(); - resultData.putByteArray(ApgHandler.RESULT_NEW_KEY, + resultData.putByteArray(RESULT_NEW_KEY, Utils.PGPSecretKeyRingToBytes(masterKeyRing)); - resultData.putByteArray(ApgHandler.RESULT_NEW_KEY2, - Utils.PGPSecretKeyRingToBytes(subKeyRing)); - sendMessageToHandler(ApgHandler.MESSAGE_OKAY, null, resultData); + resultData.putByteArray(RESULT_NEW_KEY2, Utils.PGPSecretKeyRingToBytes(subKeyRing)); + sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData); } catch (Exception e) { - Log.e(Constants.TAG, "Creating initial key failed: +" + e); + sendErrorToHandler(e); + } + + break; + + case ACTION_ENCRYPT_SIGN_BYTES: + + try { + // Input + long secretKeyId = data.getLong(SECRET_KEY_ID); + String passphrase = data.getString(PASSPHRASE); + + byte[] bytes = data.getByteArray(BYTES); + + boolean useAsciiArmour = data.getBoolean(USE_ASCII_AMOR); + long encryptionKeyIds[] = data.getLongArray(ENCRYPTION_KEYS_IDS); + long signatureKeyId = data.getLong(SIGNATURE_KEY_ID); + int compressionId = data.getInt(COMPRESSION_ID); + boolean generateSignature = data.getBoolean(GENERATE_SIGNATURE); + boolean signOnly = data.getBoolean(SIGN_ONLY); + + // Operation + ByteArrayInputStream inStream = new ByteArrayInputStream(bytes); + int inLength = bytes.length; + + InputData inputData = new InputData(inStream, inLength); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + + if (generateSignature) { + Apg.generateSignature(this, inputData, outStream, useAsciiArmour, false, + secretKeyId, Apg.getCachedPassPhrase(secretKeyId), Preferences + .getPreferences(this).getDefaultHashAlgorithm(), Preferences + .getPreferences(this).getForceV3Signatures(), this); + } else if (signOnly) { + Apg.signText(this, inputData, outStream, secretKeyId, Apg + .getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this) + .getDefaultHashAlgorithm(), Preferences.getPreferences(this) + .getForceV3Signatures(), this); + } else { + Apg.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, + signatureKeyId, Apg.getCachedPassPhrase(signatureKeyId), this, + Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(), + Preferences.getPreferences(this).getDefaultHashAlgorithm(), + compressionId, Preferences.getPreferences(this).getForceV3Signatures(), + passphrase); + } + + outStream.close(); + + // Output + Bundle resultData = new Bundle(); + + // if (encryptionTarget != Id.target.file) { + // if (out instanceof ByteArrayOutputStream) { + if (useAsciiArmour) { + String output = new String(outStream.toByteArray()); + if (generateSignature) { + resultData.putString(RESULT_SIGNATURE_TEXT, output); + } else { + resultData.putString(RESULT_ENCRYPTED_MESSAGE, output); + } + } else { + byte output[] = outStream.toByteArray(); + if (generateSignature) { + resultData.putByteArray(RESULT_SIGNATURE_DATA, output); + } else { + resultData.putByteArray(RESULT_ENCRYPTED_DATA, output); + } + } + // } else if (out instanceof FileOutputStream) { + // String fileName = dataDestination.getStreamFilename(); + // String uri = "content://" + DataProvider.AUTHORITY + "/data/" + fileName; + // resultData.putString(RESULT_URI, uri); + // } else { + // sendErrorToHandler(new Apg.GeneralException("No output-data found.")); + // } + // } + + sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData); + } catch (Exception e) { + sendErrorToHandler(e); + } + + break; + + case ACTION_ENCRYPT_SIGN_FILE: + try { + // Input + long secretKeyId = data.getLong(SECRET_KEY_ID); + String passphrase = data.getString(PASSPHRASE); + + Uri fileUri = Uri.parse(data.getString(FILE_URI)); + String outputFilename = data.getString(OUTPUT_FILENAME); + + boolean useAsciiArmour = data.getBoolean(USE_ASCII_AMOR); + long encryptionKeyIds[] = data.getLongArray(ENCRYPTION_KEYS_IDS); + long signatureKeyId = data.getLong(SIGNATURE_KEY_ID); + int compressionId = data.getInt(COMPRESSION_ID); + boolean generateSignature = data.getBoolean(GENERATE_SIGNATURE); + boolean signOnly = data.getBoolean(SIGN_ONLY); + + // InputStream + long inLength = -1; + FileInputStream inStream = null; + if (fileUri.getScheme().equals("file")) { + // get the rest after "file://" + String path = Uri.decode(fileUri.toString().substring(7)); + if (path.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) { + if (!Environment.getExternalStorageState() + .equals(Environment.MEDIA_MOUNTED)) { + sendErrorToHandler(new GeneralException( + getString(R.string.error_externalStorageNotReady))); + return; + } + } + inStream = new FileInputStream(path); + File file = new File(path); + inLength = file.length(); + } + + InputData inputData = new InputData(inStream, inLength); + + // OutputStream + if (outputFilename.startsWith(Environment.getExternalStorageDirectory() + .getAbsolutePath())) { + if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + sendErrorToHandler(new GeneralException( + getString(R.string.error_externalStorageNotReady))); + return; + } + } + FileOutputStream outStream = new FileOutputStream(outputFilename); + + // Operation + if (generateSignature) { + Apg.generateSignature(this, inputData, outStream, useAsciiArmour, true, + secretKeyId, Apg.getCachedPassPhrase(secretKeyId), Preferences + .getPreferences(this).getDefaultHashAlgorithm(), Preferences + .getPreferences(this).getForceV3Signatures(), this); + } else if (signOnly) { + Apg.signText(this, inputData, outStream, secretKeyId, Apg + .getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this) + .getDefaultHashAlgorithm(), Preferences.getPreferences(this) + .getForceV3Signatures(), this); + } else { + Apg.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, + signatureKeyId, Apg.getCachedPassPhrase(signatureKeyId), this, + Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(), + Preferences.getPreferences(this).getDefaultHashAlgorithm(), + compressionId, Preferences.getPreferences(this).getForceV3Signatures(), + passphrase); + } + + outStream.close(); + + sendMessageToHandler(ApgHandler.MESSAGE_OKAY); + } catch (Exception e) { + sendErrorToHandler(e); + } + break; + + case ACTION_ENCRYPT_SIGN_STREAM: + try { + // Input + long secretKeyId = data.getLong(SECRET_KEY_ID); + String passphrase = data.getString(PASSPHRASE); + + Uri providerUri = Uri.parse(data.getString(PROVIDER_URI)); + + boolean useAsciiArmour = data.getBoolean(USE_ASCII_AMOR); + long encryptionKeyIds[] = data.getLongArray(ENCRYPTION_KEYS_IDS); + long signatureKeyId = data.getLong(SIGNATURE_KEY_ID); + int compressionId = data.getInt(COMPRESSION_ID); + boolean generateSignature = data.getBoolean(GENERATE_SIGNATURE); + boolean signOnly = data.getBoolean(SIGN_ONLY); + + // InputStream + InputStream in = getContentResolver().openInputStream(providerUri); + long inLength = Apg.getLengthOfStream(in); + + InputData inputData = new InputData(in, inLength); + + // OutputStream + String streamFilename = null; + try { + while (true) { + streamFilename = Apg.generateRandomString(32); + if (streamFilename == null) { + throw new Apg.GeneralException("couldn't generate random file name"); + } + openFileInput(streamFilename).close(); + } + } catch (FileNotFoundException e) { + // found a name that isn't used yet + } + FileOutputStream outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE); + + // Operation + + if (generateSignature) { + Apg.generateSignature(this, inputData, outStream, useAsciiArmour, true, + secretKeyId, Apg.getCachedPassPhrase(secretKeyId), Preferences + .getPreferences(this).getDefaultHashAlgorithm(), Preferences + .getPreferences(this).getForceV3Signatures(), this); + } else if (signOnly) { + Apg.signText(this, inputData, outStream, secretKeyId, Apg + .getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this) + .getDefaultHashAlgorithm(), Preferences.getPreferences(this) + .getForceV3Signatures(), this); + } else { + Apg.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, + signatureKeyId, Apg.getCachedPassPhrase(signatureKeyId), this, + Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(), + Preferences.getPreferences(this).getDefaultHashAlgorithm(), + compressionId, Preferences.getPreferences(this).getForceV3Signatures(), + passphrase); + } + + outStream.close(); + + // Output + Bundle resultData = new Bundle(); + + // if (encryptionTarget != Id.target.file) { + // if (out instanceof ByteArrayOutputStream) { + // if (useAsciiArmour) { + // String output = new String(outStream.toByteArray()); + // if (generateSignature) { + // resultData.putString(RESULT_SIGNATURE_TEXT, output); + // } else { + // resultData.putString(RESULT_ENCRYPTED_MESSAGE, output); + // } + // } else { + // byte output[] = outStream.toByteArray(); + // if (generateSignature) { + // resultData.putByteArray(RESULT_SIGNATURE_DATA, output); + // } else { + // resultData.putByteArray(RESULT_ENCRYPTED_DATA, output); + // } + // } + // } else if (out instanceof FileOutputStream) { + // String fileName = dataDestination.getStreamFilename(); + String uri = "content://" + DataProvider.AUTHORITY + "/data/" + streamFilename; + resultData.putString(RESULT_URI, uri); + // } else { + // sendErrorToHandler(new Apg.GeneralException("No output-data found.")); + // } + // } + + sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData); + } catch (Exception e) { + sendErrorToHandler(e); } break; @@ -223,6 +512,10 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { } } + private void sendMessageToHandler(Integer arg1, Bundle data) { + sendMessageToHandler(arg1, null, data); + } + private void sendMessageToHandler(Integer arg1) { sendMessageToHandler(arg1, null, null); } diff --git a/org_apg/src/org/thialfihar/android/apg/service/ApgService2.java b/org_apg/src/org/thialfihar/android/apg/service/ApgService2.java index efc4d2d0d..5b3de8050 100644 --- a/org_apg/src/org/thialfihar/android/apg/service/ApgService2.java +++ b/org_apg/src/org/thialfihar/android/apg/service/ApgService2.java @@ -34,6 +34,7 @@ import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.service.IApgService2.Stub; import org.thialfihar.android.apg.Id.database; import org.thialfihar.android.apg.R.string; +import org.thialfihar.android.apg.passphrase.PassphraseCacheService; import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.Keys; import org.thialfihar.android.apg.provider.UserIds; @@ -50,9 +51,8 @@ import android.util.Log; /** * ATTENTION: * - * This is the old ApgService used as remote service over aidl interface. - * It will be reworked! - * + * This is the old ApgService used as remote service over aidl interface. It will be reworked! + * */ public class ApgService2 extends PassphraseCacheService { private final static String TAG = "ApgService"; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java index bd883f76d..86e3bdfc8 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java @@ -22,13 +22,13 @@ import java.io.IOException; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Apg; -import org.thialfihar.android.apg.AskForSecretKeyPassPhrase; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.PausableThread; import org.thialfihar.android.apg.Preferences; import org.thialfihar.android.apg.ProgressDialogUpdater; -import org.thialfihar.android.apg.service.PassphraseCacheService; +import org.thialfihar.android.apg.passphrase.AskForPassphrase; +import org.thialfihar.android.apg.passphrase.PassphraseCacheService; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockActivity; @@ -50,7 +50,7 @@ import android.support.v4.app.Fragment; import android.widget.Toast; public class BaseActivity extends SherlockFragmentActivity implements Runnable, - ProgressDialogUpdater, AskForSecretKeyPassPhrase.PassPhraseCallbackInterface { + ProgressDialogUpdater, AskForPassphrase.PassPhraseCallbackInterface { private ProgressDialog mProgressDialog = null; private PausableThread mRunningThread = null; @@ -76,6 +76,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable, actionBar.setDisplayShowTitleEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true); + // not needed later: mPreferences = Preferences.getPreferences(this); Apg.initialize(this); @@ -88,14 +89,14 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable, } } - startCacheService(this, mPreferences); +// startCacheService(this, mPreferences); } - public static void startCacheService(Activity activity, Preferences preferences) { - Intent intent = new Intent(activity, PassphraseCacheService.class); - intent.putExtra(PassphraseCacheService.EXTRA_TTL, preferences.getPassPhraseCacheTtl()); - activity.startService(intent); - } +// public static void startCacheService(Activity activity, Preferences preferences) { +// Intent intent = new Intent(activity, PassphraseCacheService.class); +// intent.putExtra(PassphraseCacheService.EXTRA_TTL, preferences.getPassPhraseCacheTtl()); +// activity.startService(intent); +// } @Override public boolean onOptionsItemSelected(MenuItem item) { @@ -177,7 +178,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable, switch (id) { case Id.dialog.pass_phrase: { - return AskForSecretKeyPassPhrase.createDialog(this, getSecretKeyId(), this); + return AskForPassphrase.createDialog(this, getSecretKeyId(), this); } case Id.dialog.pass_phrases_do_not_match: { @@ -373,6 +374,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable, } public void passPhraseCallback(long keyId, String passPhrase) { + // TODO: Not needed anymore, now implemented in AskForSecretKeyPass Apg.setCachedPassPhrase(keyId, passPhrase); } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java index aebc958a0..310fcd915 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java @@ -207,10 +207,10 @@ public class EditKeyActivity extends SherlockFragmentActivity { Bundle data = message.getData(); PGPSecretKeyRing masterKeyRing = Utils .BytesToPGPSecretKeyRing(data - .getByteArray(ApgHandler.RESULT_NEW_KEY)); + .getByteArray(ApgService.RESULT_NEW_KEY)); PGPSecretKeyRing subKeyRing = Utils .BytesToPGPSecretKeyRing(data - .getByteArray(ApgHandler.RESULT_NEW_KEY2)); + .getByteArray(ApgService.RESULT_NEW_KEY2)); // add master key Iterator masterIt = masterKeyRing.getSecretKeys(); @@ -419,14 +419,10 @@ public class EditKeyActivity extends SherlockFragmentActivity { Bundle data = new Bundle(); data.putString(ApgService.CURRENT_PASSPHRASE, mCurrentPassPhrase); data.putString(ApgService.NEW_PASSPHRASE, mNewPassPhrase); - data.putSerializable(ApgService.USER_IDS, getUserIds(mUserIdsView)); - Vector keys = getKeys(mKeysView); data.putByteArray(ApgService.KEYS, Utils.PGPSecretKeyListToBytes(keys)); - data.putSerializable(ApgService.KEYS_USAGES, getKeysUsages(mKeysView)); - data.putLong(ApgService.MASTER_KEY_ID, getMasterKeyId()); intent.putExtra(ApgService.EXTRA_DATA, data); diff --git a/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java index a6a4efb18..af8755d12 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java @@ -16,7 +16,6 @@ package org.thialfihar.android.apg.ui; -import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; @@ -27,22 +26,28 @@ import org.thialfihar.android.apg.DataDestination; import org.thialfihar.android.apg.DataSource; import org.thialfihar.android.apg.FileDialog; import org.thialfihar.android.apg.Id; -import org.thialfihar.android.apg.InputData; -import org.thialfihar.android.apg.provider.DataProvider; +import org.thialfihar.android.apg.Preferences; +import org.thialfihar.android.apg.passphrase.AskForPassphrase; +import org.thialfihar.android.apg.service.ApgHandler; +import org.thialfihar.android.apg.service.ApgService; import org.thialfihar.android.apg.util.Choice; import org.thialfihar.android.apg.util.Compatibility; import org.thialfihar.android.apg.R; import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; import android.app.Dialog; +import android.app.ProgressDialog; import android.content.ActivityNotFoundException; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Message; +import android.os.Messenger; +import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.AnimationUtils; @@ -57,17 +62,11 @@ import android.widget.TextView; import android.widget.Toast; import android.widget.ViewFlipper; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SignatureException; import java.util.Vector; -public class EncryptActivity extends BaseActivity { +public class EncryptActivity extends SherlockFragmentActivity implements + AskForPassphrase.PassPhraseCallbackInterface { private Intent mIntent = null; private String mSubject = null; private String mSendTo = null; @@ -121,6 +120,10 @@ public class EncryptActivity extends BaseActivity { private boolean mGenerateSignature = false; + private long mSecretKeyId = 0; + + private ProgressDialogFragment mEncryptingDialog; + @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -266,7 +269,7 @@ public class EncryptActivity extends BaseActivity { adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mFileCompression.setAdapter(adapter); - int defaultFileCompression = mPreferences.getDefaultFileCompression(); + int defaultFileCompression = Preferences.getPreferences(this).getDefaultFileCompression(); for (int i = 0; i < choices.length; ++i) { if (choices[i].getId() == defaultFileCompression) { mFileCompression.setSelection(i); @@ -277,7 +280,7 @@ public class EncryptActivity extends BaseActivity { mDeleteAfter = (CheckBox) findViewById(R.id.deleteAfterEncryption); mAsciiArmour = (CheckBox) findViewById(R.id.asciiArmour); - mAsciiArmour.setChecked(mPreferences.getDefaultAsciiArmour()); + mAsciiArmour.setChecked(Preferences.getPreferences(this).getDefaultAsciiArmour()); mAsciiArmour.setOnClickListener(new OnClickListener() { public void onClick(View view) { guessOutputFilename(); @@ -657,7 +660,7 @@ public class EncryptActivity extends BaseActivity { @Override public void passPhraseCallback(long keyId, String passPhrase) { - super.passPhraseCallback(keyId, passPhrase); + // super.passPhraseCallback(keyId, passPhrase); if (mEncryptTarget == Id.target.file) { askForOutputFilename(); } else { @@ -667,122 +670,151 @@ public class EncryptActivity extends BaseActivity { private void encryptStart() { showDialog(Id.dialog.encrypting); - startThread(); + // startThread(); + + boolean useAsciiArmour = true; + long encryptionKeyIds[] = null; + long signatureKeyId = 0; + int compressionId = 0; + boolean signOnly = false; + + String passPhrase = null; + if (mMode.getCurrentView().getId() == R.id.modeSymmetric) { + passPhrase = mPassPhrase.getText().toString(); + if (passPhrase.length() == 0) { + passPhrase = null; + } + } else { + encryptionKeyIds = mEncryptionKeyIds; + signatureKeyId = getSecretKeyId(); + signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0); + } + + fillDataSource(signOnly && !mReturnResult); + fillDataDestination(); + + // Send all information needed to service to edit key in other thread + Intent intent = new Intent(this, ApgService.class); + + // fill values for this action + Bundle data = new Bundle(); + + // choose default settings, action and data bundle by target + if (mEncryptTarget == Id.target.file) { + useAsciiArmour = mAsciiArmour.isChecked(); + compressionId = ((Choice) mFileCompression.getSelectedItem()).getId(); + + intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_ENCRYPT_SIGN_FILE); + + data.putString(ApgService.FILE_URI, mDataSource.getUri().toString()); + + } else { + useAsciiArmour = true; + compressionId = Preferences.getPreferences(this).getDefaultMessageCompression(); + + intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_ENCRYPT_SIGN_BYTES); + + data.putByteArray(ApgService.BYTES, mDataSource.getBytes()); + } + + if (mOverrideAsciiArmour) { + useAsciiArmour = mAsciiArmourDemand; + } + + data.putLong(ApgService.SECRET_KEY_ID, getSecretKeyId()); + data.putBoolean(ApgService.USE_ASCII_AMOR, useAsciiArmour); + data.putLongArray(ApgService.ENCRYPTION_KEYS_IDS, encryptionKeyIds); + data.putLong(ApgService.SIGNATURE_KEY_ID, signatureKeyId); + data.putInt(ApgService.COMPRESSION_ID, compressionId); + data.putBoolean(ApgService.GENERATE_SIGNATURE, mGenerateSignature); + data.putBoolean(ApgService.SIGN_ONLY, signOnly); + + intent.putExtra(ApgService.EXTRA_DATA, data); + + // show progress dialog + mEncryptingDialog = ProgressDialogFragment.newInstance(R.string.progress_encrypting, + ProgressDialog.STYLE_HORIZONTAL); + + // Message is received after saving is done in ApgService + ApgHandler saveHandler = new ApgHandler(this, mEncryptingDialog) { + public void handleMessage(Message message) { + // handle messages by standard ApgHandler first + super.handleMessage(message); + + if (message.arg1 == ApgHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle data = message.getData(); + + String output; + switch (mEncryptTarget) { + case Id.target.clipboard: + output = data.getString(ApgService.RESULT_ENCRYPTED_MESSAGE); + Log.d(Constants.TAG, "output: " + output); + Compatibility.copyToClipboard(EncryptActivity.this, output); + Toast.makeText(EncryptActivity.this, + R.string.encryptionToClipboardSuccessful, Toast.LENGTH_SHORT) + .show(); + break; + + case Id.target.email: + if (mReturnResult) { + Intent intent = new Intent(); + intent.putExtras(data); + setResult(RESULT_OK, intent); + finish(); + return; + } + + output = data.getString(ApgService.RESULT_ENCRYPTED_MESSAGE); + Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); + emailIntent.setType("text/plain; charset=utf-8"); + emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message); + if (mSubject != null) { + emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, mSubject); + } + if (mSendTo != null) { + emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, + new String[] { mSendTo }); + } + EncryptActivity.this.startActivity(Intent.createChooser(emailIntent, + getString(R.string.title_sendEmail))); + break; + + case Id.target.file: + Toast.makeText(EncryptActivity.this, R.string.encryptionSuccessful, + Toast.LENGTH_SHORT).show(); + if (mDeleteAfter.isChecked()) { + // TODO: Reimplement that! + // setDeleteFile(mInputFilename); + // showDialog(Id.dialog.delete_file); + } + break; + + default: + // shouldn't happen + break; + + } + } + }; + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(ApgService.EXTRA_MESSENGER, messenger); + + mEncryptingDialog.show(getSupportFragmentManager(), "dialog"); + + // start service with intent + startService(intent); } - @Override - public void run() { - String error = null; - Bundle data = new Bundle(); - Message msg = new Message(); + public void setSecretKeyId(long id) { + mSecretKeyId = id; + } - try { - InputData in; - OutputStream out; - boolean useAsciiArmour = true; - long encryptionKeyIds[] = null; - long signatureKeyId = 0; - int compressionId = 0; - boolean signOnly = false; - - String passPhrase = null; - if (mMode.getCurrentView().getId() == R.id.modeSymmetric) { - passPhrase = mPassPhrase.getText().toString(); - if (passPhrase.length() == 0) { - passPhrase = null; - } - } else { - encryptionKeyIds = mEncryptionKeyIds; - signatureKeyId = getSecretKeyId(); - signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0); - } - - fillDataSource(signOnly && !mReturnResult); - fillDataDestination(); - - // streams - in = mDataSource.getInputData(this, true); - out = mDataDestination.getOutputStream(this); - - if (mEncryptTarget == Id.target.file) { - useAsciiArmour = mAsciiArmour.isChecked(); - compressionId = ((Choice) mFileCompression.getSelectedItem()).getId(); - } else { - useAsciiArmour = true; - compressionId = mPreferences.getDefaultMessageCompression(); - } - - if (mOverrideAsciiArmour) { - useAsciiArmour = mAsciiArmourDemand; - } - - if (mGenerateSignature) { - Apg.generateSignature(this, in, out, useAsciiArmour, mDataSource.isBinary(), - getSecretKeyId(), Apg.getCachedPassPhrase(getSecretKeyId()), - mPreferences.getDefaultHashAlgorithm(), - mPreferences.getForceV3Signatures(), this); - } else if (signOnly) { - Apg.signText(this, in, out, getSecretKeyId(), - Apg.getCachedPassPhrase(getSecretKeyId()), - mPreferences.getDefaultHashAlgorithm(), - mPreferences.getForceV3Signatures(), this); - } else { - Apg.encrypt(this, in, out, useAsciiArmour, encryptionKeyIds, signatureKeyId, - Apg.getCachedPassPhrase(signatureKeyId), this, - mPreferences.getDefaultEncryptionAlgorithm(), - mPreferences.getDefaultHashAlgorithm(), compressionId, - mPreferences.getForceV3Signatures(), passPhrase); - } - - out.close(); - if (mEncryptTarget != Id.target.file) { - - if (out instanceof ByteArrayOutputStream) { - if (useAsciiArmour) { - String extraData = new String(((ByteArrayOutputStream) out).toByteArray()); - if (mGenerateSignature) { - data.putString(Apg.EXTRA_SIGNATURE_TEXT, extraData); - } else { - data.putString(Apg.EXTRA_ENCRYPTED_MESSAGE, extraData); - } - } else { - byte extraData[] = ((ByteArrayOutputStream) out).toByteArray(); - if (mGenerateSignature) { - data.putByteArray(Apg.EXTRA_SIGNATURE_DATA, extraData); - } else { - data.putByteArray(Apg.EXTRA_ENCRYPTED_DATA, extraData); - } - } - } else if (out instanceof FileOutputStream) { - String fileName = mDataDestination.getStreamFilename(); - String uri = "content://" + DataProvider.AUTHORITY + "/data/" + fileName; - data.putString(Apg.EXTRA_RESULT_URI, uri); - } else { - throw new Apg.GeneralException("No output-data found."); - } - } - } catch (IOException e) { - error = "" + e; - } catch (PGPException e) { - error = "" + e; - } catch (NoSuchProviderException e) { - error = "" + e; - } catch (NoSuchAlgorithmException e) { - error = "" + e; - } catch (SignatureException e) { - error = "" + e; - } catch (Apg.GeneralException e) { - error = "" + e; - } - - data.putInt(Constants.extras.STATUS, Id.message.done); - - if (error != null) { - data.putString(Apg.EXTRA_ERROR, error); - } - - msg.setData(data); - sendMessage(msg); + public long getSecretKeyId() { + return mSecretKeyId; } private void updateView() { @@ -911,68 +943,6 @@ public class EncryptActivity extends BaseActivity { super.onActivityResult(requestCode, resultCode, data); } - @Override - public void doneCallback(Message msg) { - super.doneCallback(msg); - - removeDialog(Id.dialog.encrypting); - - Bundle data = msg.getData(); - String error = data.getString(Apg.EXTRA_ERROR); - if (error != null) { - Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT) - .show(); - return; - } - switch (mEncryptTarget) { - case Id.target.clipboard: { - String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE); - Compatibility.copyToClipboard(this, message); - Toast.makeText(this, R.string.encryptionToClipboardSuccessful, Toast.LENGTH_SHORT) - .show(); - break; - } - - case Id.target.email: { - if (mReturnResult) { - Intent intent = new Intent(); - intent.putExtras(data); - setResult(RESULT_OK, intent); - finish(); - return; - } - - String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE); - Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); - emailIntent.setType("text/plain; charset=utf-8"); - emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message); - if (mSubject != null) { - emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, mSubject); - } - if (mSendTo != null) { - emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { mSendTo }); - } - EncryptActivity.this.startActivity(Intent.createChooser(emailIntent, - getString(R.string.title_sendEmail))); - break; - } - - case Id.target.file: { - Toast.makeText(this, R.string.encryptionSuccessful, Toast.LENGTH_SHORT).show(); - if (mDeleteAfter.isChecked()) { - setDeleteFile(mInputFilename); - showDialog(Id.dialog.delete_file); - } - break; - } - - default: { - // shouldn't happen - break; - } - } - } - @Override protected Dialog onCreateDialog(int id) { switch (id) { diff --git a/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java index 8b7ed59a7..b602e92b8 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java @@ -22,6 +22,7 @@ import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.Preferences; +import org.thialfihar.android.apg.passphrase.PassphraseCacheService; import org.thialfihar.android.apg.ui.widget.IntegerListPreference; import org.thialfihar.android.apg.R; @@ -67,7 +68,9 @@ public class PreferencesActivity extends SherlockPreferenceActivity { mPassPhraseCacheTtl.setValue(newValue.toString()); mPassPhraseCacheTtl.setSummary(mPassPhraseCacheTtl.getEntry()); mPreferences.setPassPhraseCacheTtl(Integer.parseInt(newValue.toString())); - BaseActivity.startCacheService(PreferencesActivity.this, mPreferences); + + // restart cache service with new ttl + PassphraseCacheService.startCacheService(PreferencesActivity.this); return false; } }); diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java index a1b5e753d..b0475c147 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java @@ -18,9 +18,9 @@ package org.thialfihar.android.apg.ui; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Apg; -import org.thialfihar.android.apg.AskForSecretKeyPassPhrase; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; +import org.thialfihar.android.apg.passphrase.AskForPassphrase; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; @@ -135,7 +135,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli case Id.dialog.pass_phrase: { long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()) .getGroupId(mSelectedItem); - return AskForSecretKeyPassPhrase.createDialog(this, keyId, this); + return AskForPassphrase.createDialog(this, keyId, this); } default: { diff --git a/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java b/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java index 7c19317bd..5f2c76a7a 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java @@ -285,7 +285,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor // get new key from data bundle returned from service Bundle data = message.getData(); PGPSecretKeyRing newKeyRing = Utils.BytesToPGPSecretKeyRing(data - .getByteArray(ApgHandler.RESULT_NEW_KEY)); + .getByteArray(ApgService.RESULT_NEW_KEY)); boolean isMasterKey = (mEditors.getChildCount() == 0);