working on externalizing encrypt methods into the service

This commit is contained in:
Dominik 2012-06-09 03:46:30 +03:00
parent 7b61ad24d7
commit 5a51f79126
22 changed files with 650 additions and 280 deletions

View File

@ -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!)

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org> 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. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.thialfihar.android.apg"
@ -32,7 +31,7 @@
android:hardwareAccelerated="true"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/Theme.Sherlock.Light.ForceOverflow" >
android:theme="@style/Theme.Sherlock.Light.ForceOverflow" android:name="ApgApplication">
<activity
android:name=".ui.MainActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
@ -220,10 +219,10 @@
android:label="@string/title_about"
android:theme="@style/Theme.Sherlock.Light.Dialog" />
<activity
android:name="org.thialfihar.android.apg.ui.HelpActivity"
android:name=".ui.HelpActivity"
android:label="@string/title_help" />
<service android:name=".service.PassphraseCacheService" />
<service android:name=".service.password.PassphraseCacheService" />
<service android:name=".service.ApgService" />
<!-- TODO: need to be moved into new service model -->
@ -247,7 +246,7 @@
android:authorities="org.thialfihar.android.apg.provider"
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />
<provider
android:name="org.thialfihar.android.apg.provider.ApgServiceBlobProvider"
android:name=".provider.blob.ApgServiceBlobProvider"
android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider"
android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" />
</application>

View File

@ -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];

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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() {

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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() {
// }
//}

View File

@ -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;

View File

@ -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);
}

View File

@ -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";

View File

@ -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);
}

View File

@ -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<PGPSecretKey> 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<PGPSecretKey> 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);

View File

@ -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) {

View File

@ -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;
}
});

View File

@ -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: {

View File

@ -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);