aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThialfihar <thialfihar@gmail.com>2010-07-09 20:55:17 +0000
committerThialfihar <thialfihar@gmail.com>2010-07-09 20:55:17 +0000
commit2c47734f0fdb1dccfd41dec8cfad8d93f311ea52 (patch)
tree121b80ff878301455ac21c651c326e725fe5d992 /src
parent3ac472125a7ad3b7b600c32129a50def3b8a1b8a (diff)
downloadopen-keychain-2c47734f0fdb1dccfd41dec8cfad8d93f311ea52.tar.gz
open-keychain-2c47734f0fdb1dccfd41dec8cfad8d93f311ea52.tar.bz2
open-keychain-2c47734f0fdb1dccfd41dec8cfad8d93f311ea52.zip
trying to add support for various source and destination modes for encryption and decryption (String, byte[], filename, content stream), also more Intent options added
Diffstat (limited to 'src')
-rw-r--r--src/org/thialfihar/android/apg/Apg.java46
-rw-r--r--src/org/thialfihar/android/apg/DataDestination.java79
-rw-r--r--src/org/thialfihar/android/apg/DataSource.java88
-rw-r--r--src/org/thialfihar/android/apg/DecryptActivity.java169
-rw-r--r--src/org/thialfihar/android/apg/EncryptActivity.java129
-rw-r--r--src/org/thialfihar/android/apg/GeneralActivity.java2
-rw-r--r--src/org/thialfihar/android/apg/Id.java7
-rw-r--r--src/org/thialfihar/android/apg/InputData.java25
-rw-r--r--src/org/thialfihar/android/apg/KeyListActivity.java6
-rw-r--r--src/org/thialfihar/android/apg/MailListActivity.java2
-rw-r--r--src/org/thialfihar/android/apg/MainActivity.java6
-rw-r--r--src/org/thialfihar/android/apg/PreferencesActivity.java1
-rw-r--r--src/org/thialfihar/android/apg/PublicKeyListActivity.java2
-rw-r--r--src/org/thialfihar/android/apg/SecretKeyListActivity.java2
-rw-r--r--src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java2
15 files changed, 380 insertions, 186 deletions
diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java
index d606a553c..e2c6df5b9 100644
--- a/src/org/thialfihar/android/apg/Apg.java
+++ b/src/org/thialfihar/android/apg/Apg.java
@@ -117,7 +117,9 @@ public class Apg {
public static final String EXTRA_STATUS = "status";
public static final String EXTRA_ERROR = "error";
public static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage";
+ public static final String EXTRA_DECRYPTED_DATA = "decryptedData";
public static final String EXTRA_ENCRYPTED_MESSAGE = "encryptedMessage";
+ public static final String EXTRA_ENCRYPTED_DATA = "encryptedData";
public static final String EXTRA_RESULT_URI = "resultUri";
public static final String EXTRA_SIGNATURE = "signature";
public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId";
@@ -135,6 +137,8 @@ public class Apg {
public static final String EXTRA_PROGRESS = "progress";
public static final String EXTRA_MAX = "max";
public static final String EXTRA_ACCOUNT = "account";
+ public static final String EXTRA_ASCII_ARMOUR = "asciiArmour";
+ public static final String EXTRA_BINARY = "binary";
public static final String AUTHORITY = DataProvider.AUTHORITY;
@@ -576,7 +580,7 @@ public class Apg {
}
public static Bundle importKeyRings(Activity context, int type,
- InputStream inStream, long dataLength,
+ InputData data,
ProgressDialogUpdater progress)
throws GeneralException, FileNotFoundException, PGPException, IOException {
Bundle returnData = new Bundle();
@@ -591,7 +595,7 @@ public class Apg {
throw new GeneralException(context.getString(R.string.error_externalStorageNotReady));
}
- PositionAwareInputStream progressIn = new PositionAwareInputStream(inStream);
+ PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream());
// need to have access to the bufferedInput, so we can reuse it for the possible
// PGPObject chunks after the first one, e.g. files with several consecutive ASCII
// armour blocks
@@ -637,7 +641,7 @@ public class Apg {
} else if (retValue == Id.return_value.ok) {
++newKeys;
}
- progress.setProgress((int)(100 * progressIn.position() / dataLength), 100);
+ progress.setProgress((int)(100 * progressIn.position() / data.getSize()), 100);
obj = objectFactory.nextObject();
}
}
@@ -1110,8 +1114,7 @@ public class Apg {
}
public static void encrypt(Context context,
- InputStream inStream, OutputStream outStream,
- long dataLength,
+ InputData data, OutputStream outStream,
boolean armored,
long encryptionKeyIds[], long signatureKeyId,
String signaturePassPhrase,
@@ -1213,14 +1216,15 @@ public class Apg {
long done = 0;
int n = 0;
byte[] buffer = new byte[1 << 16];
- while ((n = inStream.read(buffer)) > 0) {
+ InputStream in = data.getInputStream();
+ while ((n = in.read(buffer)) > 0) {
pOut.write(buffer, 0, n);
if (signatureKeyId != 0) {
signatureGenerator.update(buffer, 0, n);
}
done += n;
- if (dataLength != 0) {
- progress.setProgress((int) (20 + (95 - 20) * done / dataLength), 100);
+ if (data.getSize() != 0) {
+ progress.setProgress((int) (20 + (95 - 20) * done / data.getSize()), 100);
}
}
@@ -1242,7 +1246,7 @@ public class Apg {
}
public static void signText(Context context,
- InputStream inStream, OutputStream outStream,
+ InputData data, OutputStream outStream,
long signatureKeyId, String signaturePassPhrase,
int hashAlgorithm,
ProgressDialogUpdater progress)
@@ -1294,6 +1298,7 @@ public class Apg {
armorOut.beginClearText(hashAlgorithm);
ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
+ InputStream inStream = data.getInputStream();
int lookAhead = readInputLine(lineOut, inStream);
processLine(armorOut, signatureGenerator, lineOut.toByteArray());
@@ -1319,9 +1324,9 @@ public class Apg {
progress.setProgress(R.string.progress_done, 100, 100);
}
- public static long getDecryptionKeyId(Context context, InputStream inStream)
+ public static long getDecryptionKeyId(Context context, InputData data)
throws GeneralException, NoAsymmetricEncryptionException, IOException {
- InputStream in = PGPUtil.getDecoderStream(inStream);
+ InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
@@ -1365,9 +1370,9 @@ public class Apg {
return secretKey.getKeyID();
}
- public static boolean hasSymmetricEncryption(Context context, InputStream inStream)
+ public static boolean hasSymmetricEncryption(Context context, InputData data)
throws GeneralException, IOException {
- InputStream in = PGPUtil.getDecoderStream(inStream);
+ InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
@@ -1395,8 +1400,7 @@ public class Apg {
}
public static Bundle decrypt(Context context,
- PositionAwareInputStream inStream, OutputStream outStream,
- long dataLength,
+ InputData data, OutputStream outStream,
String passPhrase, ProgressDialogUpdater progress,
boolean assumeSymmetric)
throws IOException, GeneralException, PGPException, SignatureException {
@@ -1404,7 +1408,7 @@ public class Apg {
passPhrase = "";
}
Bundle returnData = new Bundle();
- InputStream in = PGPUtil.getDecoderStream(inStream);
+ InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
@@ -1557,7 +1561,7 @@ public class Apg {
}
int n = 0;
int done = 0;
- long startPos = inStream.position();
+ long startPos = data.getStreamPosition();
while ((n = dataIn.read(buffer)) > 0) {
out.write(buffer, 0, n);
done += n;
@@ -1571,11 +1575,11 @@ public class Apg {
}
// unknown size, but try to at least have a moving, slowing down progress bar
currentProgress = startProgress + (endProgress - startProgress) * done / (done + 100000);
- if (dataLength - startPos == 0) {
+ if (data.getSize() - startPos == 0) {
currentProgress = endProgress;
} else {
currentProgress = (int)(startProgress + (endProgress - startProgress) *
- (inStream.position() - startPos) / (dataLength - startPos));
+ (data.getStreamPosition() - startPos) / (data.getSize() - startPos));
}
progress.setProgress(currentProgress, 100);
}
@@ -1609,13 +1613,13 @@ public class Apg {
}
public static Bundle verifyText(Context context,
- InputStream inStream, OutputStream outStream,
+ InputData data, OutputStream outStream,
ProgressDialogUpdater progress)
throws IOException, GeneralException, PGPException, SignatureException {
Bundle returnData = new Bundle();
ByteArrayOutputStream out = new ByteArrayOutputStream();
- ArmoredInputStream aIn = new ArmoredInputStream(inStream);
+ ArmoredInputStream aIn = new ArmoredInputStream(data.getInputStream());
progress.setProgress(R.string.progress_done, 0, 100);
diff --git a/src/org/thialfihar/android/apg/DataDestination.java b/src/org/thialfihar/android/apg/DataDestination.java
new file mode 100644
index 000000000..28cacd7ae
--- /dev/null
+++ b/src/org/thialfihar/android/apg/DataDestination.java
@@ -0,0 +1,79 @@
+package org.thialfihar.android.apg;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.thialfihar.android.apg.Apg.GeneralException;
+
+import android.content.Context;
+import android.os.Environment;
+
+public class DataDestination {
+ private String mStreamFilename;
+ private String mFilename;
+ private int mMode = Id.mode.undefined;
+
+ public DataDestination() {
+
+ }
+
+ public void setMode(int mode) {
+ mMode = mode;
+ }
+
+ public void setFilename(String filename) {
+ mFilename = filename;
+ }
+
+ public String getStreamFilename() {
+ return mStreamFilename;
+ }
+
+ protected OutputStream getOutputStream(Context context)
+ throws Apg.GeneralException, FileNotFoundException, IOException {
+ OutputStream out = null;
+ mStreamFilename = null;
+
+ switch (mMode) {
+ case Id.mode.stream: {
+ try {
+ while (true) {
+ mStreamFilename = Apg.generateRandomString(32);
+ if (mStreamFilename == null) {
+ throw new Apg.GeneralException("couldn't generate random file name");
+ }
+ context.openFileInput(mStreamFilename).close();
+ }
+ } catch (FileNotFoundException e) {
+ // found a name that isn't used yet
+ }
+ out = context.openFileOutput(mStreamFilename, Context.MODE_PRIVATE);
+ break;
+ }
+
+ case Id.mode.byte_array: {
+ out = new ByteArrayOutputStream();
+ break;
+ }
+
+ case Id.mode.file: {
+ if (mFilename.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ throw new GeneralException(context.getString(R.string.error_externalStorageNotReady));
+ }
+ }
+ out = new FileOutputStream(mFilename);
+ break;
+ }
+
+ default: {
+ break;
+ }
+ }
+
+ return out;
+ }
+}
diff --git a/src/org/thialfihar/android/apg/DataSource.java b/src/org/thialfihar/android/apg/DataSource.java
new file mode 100644
index 000000000..159cdb349
--- /dev/null
+++ b/src/org/thialfihar/android/apg/DataSource.java
@@ -0,0 +1,88 @@
+package org.thialfihar.android.apg;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.thialfihar.android.apg.Apg.GeneralException;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.Environment;
+
+public class DataSource {
+ private Uri mContentUri = null;
+ private String mText = null;
+ private byte[] mData = null;
+
+ public DataSource() {
+
+ }
+
+ public void setUri(Uri uri) {
+ mContentUri = uri;
+ }
+
+ public void setUri(String uri) {
+ if (uri.startsWith("/")) {
+ setUri(Uri.parse("file://" + uri));
+ } else {
+ setUri(Uri.parse(uri));
+ }
+ }
+
+ public void setText(String text) {
+ mText = text;
+ }
+
+ public void setData(byte[] data) {
+ mData = data;
+ }
+
+ public InputData getInputData(Context context, boolean withSize)
+ throws GeneralException, FileNotFoundException, IOException {
+ InputStream in = null;
+ long size = 0;
+
+ if (mContentUri != null) {
+ if (mContentUri.getScheme().equals("file")) {
+ // get the rest after "file://"
+ String path = mContentUri.toString().substring(6);
+ if (path.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ throw new GeneralException(context.getString(R.string.error_externalStorageNotReady));
+ }
+ }
+ in = new FileInputStream(path);
+ File file = new File(path);
+ if (withSize) {
+ size = file.length();
+ }
+ } else {
+ in = context.getContentResolver().openInputStream(mContentUri);
+ if (withSize) {
+ InputStream tmp = context.getContentResolver().openInputStream(mContentUri);
+ size = Apg.getLengthOfStream(tmp);
+ tmp.close();
+ }
+ }
+ } else if (mText != null || mData != null) {
+ byte[] bytes = null;
+ if (mData != null) {
+ bytes = mData;
+ } else {
+ bytes = mText.getBytes();
+ }
+ in = new ByteArrayInputStream(bytes);
+ if (withSize) {
+ size = bytes.length;
+ }
+ }
+
+ return new InputData(in, size);
+ }
+
+}
diff --git a/src/org/thialfihar/android/apg/DecryptActivity.java b/src/org/thialfihar/android/apg/DecryptActivity.java
index 571edbdf5..d8b7ccd9c 100644
--- a/src/org/thialfihar/android/apg/DecryptActivity.java
+++ b/src/org/thialfihar/android/apg/DecryptActivity.java
@@ -16,12 +16,9 @@
package org.thialfihar.android.apg;
-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.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -88,6 +85,11 @@ public class DecryptActivity extends BaseActivity {
private String mOutputFilename = null;
private Uri mContentUri = null;
+ private byte[] mData = null;
+ private boolean mReturnBinary = false;
+
+ private DataSource mDataSource = null;
+ private DataDestination mDataDestination = null;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -186,21 +188,26 @@ public class DecryptActivity extends BaseActivity {
if (extras == null) {
extras = new Bundle();
}
- String data = extras.getString(Apg.EXTRA_TEXT);
- if (data != null) {
- Matcher matcher = Apg.PGP_MESSAGE.matcher(data);
+
+ mData = extras.getByteArray(Apg.EXTRA_DATA);
+ String textData = null;
+ if (mData == null) {
+ textData = extras.getString(Apg.EXTRA_TEXT);
+ }
+ if (textData != null) {
+ Matcher matcher = Apg.PGP_MESSAGE.matcher(textData);
if (matcher.matches()) {
- data = matcher.group(1);
+ textData = matcher.group(1);
// replace non breakable spaces
- data = data.replaceAll("\\xa0", " ");
- mMessage.setText(data);
+ textData = textData.replaceAll("\\xa0", " ");
+ mMessage.setText(textData);
} else {
- matcher = Apg.PGP_SIGNED_MESSAGE.matcher(data);
+ matcher = Apg.PGP_SIGNED_MESSAGE.matcher(textData);
if (matcher.matches()) {
- data = matcher.group(1);
+ textData = matcher.group(1);
// replace non breakable spaces
- data = data.replaceAll("\\xa0", " ");
- mMessage.setText(data);
+ textData = textData.replaceAll("\\xa0", " ");
+ mMessage.setText(textData);
mDecryptButton.setText(R.string.btn_verify);
}
}
@@ -208,15 +215,12 @@ public class DecryptActivity extends BaseActivity {
mReplyTo = extras.getString(Apg.EXTRA_REPLY_TO);
mSubject = extras.getString(Apg.EXTRA_SUBJECT);
} else if (Apg.Intent.DECRYPT_FILE.equals(mIntent.getAction())) {
+ mInputFilename = mIntent.getDataString();
if ("file".equals(mIntent.getScheme())) {
- mInputFilename = mIntent.getDataString().replace("file://", "");
- mFilename.setText(mInputFilename);
- guessOutputFilename();
- } else if ("content".equals(mIntent.getScheme())) {
- mInputFilename = mIntent.getDataString();
- mFilename.setText(mInputFilename);
- guessOutputFilename();
+ mInputFilename = mInputFilename.substring(6);
}
+ mFilename.setText(mInputFilename);
+ guessOutputFilename();
mSource.setInAnimation(null);
mSource.setOutAnimation(null);
while (mSource.getCurrentView().getId() != R.id.sourceFile) {
@@ -224,11 +228,15 @@ public class DecryptActivity extends BaseActivity {
}
} else if (Apg.Intent.DECRYPT_AND_RETURN.equals(mIntent.getAction())) {
mContentUri = mIntent.getData();
+ Bundle extras = mIntent.getExtras();
+ if (extras == null) {
+ extras = new Bundle();
+ }
+
+ mReturnBinary = extras.getBoolean(Apg.EXTRA_BINARY, false);
+
if (mContentUri == null) {
- Bundle extras = mIntent.getExtras();
- if (extras == null) {
- extras = new Bundle();
- }
+ mData = extras.getByteArray(Apg.EXTRA_DATA);
String data = extras.getString(Apg.EXTRA_TEXT);
if (data != null) {
Matcher matcher = Apg.PGP_MESSAGE.matcher(data);
@@ -397,19 +405,9 @@ public class DecryptActivity extends BaseActivity {
// else treat it as an decrypted message/file
mSignedOnly = false;
String error = null;
+ fillDataSource();
try {
- InputStream in;
- if (mContentUri != null) {
- in = getContentResolver().openInputStream(mContentUri);
- } else if (mDecryptTarget == Id.target.file) {
- if (mInputFilename.startsWith("file")) {
- in = new FileInputStream(mInputFilename);
- } else {
- in = getContentResolver().openInputStream(Uri.parse(mInputFilename));
- }
- } else {
- in = new ByteArrayInputStream(mMessage.getText().toString().getBytes());
- }
+ InputData in = mDataSource.getInputData(this, false);
try {
setSecretKeyId(Apg.getDecryptionKeyId(this, in));
if (getSecretKeyId() == Id.key.none) {
@@ -418,19 +416,7 @@ public class DecryptActivity extends BaseActivity {
mAssumeSymmetricEncryption = false;
} catch (Apg.NoAsymmetricEncryptionException e) {
setSecretKeyId(Id.key.symmetric);
- // look at the file/message again to check whether there's
- // symmetric encryption data in there
- if (mContentUri != null) {
- in = getContentResolver().openInputStream(mContentUri);
- } else if (mDecryptTarget == Id.target.file) {
- if (mInputFilename.startsWith("file")) {
- in = new FileInputStream(mInputFilename);
- } else {
- in = getContentResolver().openInputStream(Uri.parse(mInputFilename));
- }
- } else {
- in = new ByteArrayInputStream(mMessage.getText().toString().getBytes());
- }
+ in = mDataSource.getInputData(this, false);
if (!Apg.hasSymmetricEncryption(this, in)) {
throw new Apg.GeneralException(getString(R.string.error_noKnownEncryptionFound));
}
@@ -500,60 +486,32 @@ public class DecryptActivity extends BaseActivity {
Bundle data = new Bundle();
Message msg = new Message();
-
+ fillDataSource();
+ fillDataDestination();
try {
- PositionAwareInputStream in = null;
- OutputStream out = null;
- String randomString = null;
- long size = 0;
-
- if (mContentUri != null) {
- in = new PositionAwareInputStream(getContentResolver().openInputStream(mContentUri));
- size = Apg.getLengthOfStream(getContentResolver().openInputStream(mContentUri));
- try {
- while (true) {
- randomString = Apg.generateRandomString(32);
- if (randomString == null) {
- throw new Apg.GeneralException("couldn't generate random file name");
- }
- this.openFileInput(randomString).close();
- }
- } catch (FileNotFoundException e) {
- // found a name that isn't used yet
- }
- out = openFileOutput(randomString, MODE_PRIVATE);
- } else if (mDecryptTarget == Id.target.message) {
- String messageData = mMessage.getText().toString();
- in = new PositionAwareInputStream(new ByteArrayInputStream(messageData.getBytes()));
- out = new ByteArrayOutputStream();
- size = messageData.getBytes().length;
- } else {
- if (mInputFilename.startsWith("content")) {
- size = Apg.getLengthOfStream(getContentResolver().openInputStream(Uri.parse(mInputFilename)));
- in = new PositionAwareInputStream(
- getContentResolver().openInputStream(Uri.parse(mInputFilename)));
- } else {
- in = new PositionAwareInputStream(new FileInputStream(mInputFilename));
- File file = new File(mInputFilename);
- size = file.length();
- }
- out = new FileOutputStream(mOutputFilename);
- }
+ InputData in = mDataSource.getInputData(this, true);
+ OutputStream out = mDataDestination.getOutputStream(this);
if (mSignedOnly) {
data = Apg.verifyText(this, in, out, this);
} else {
- data = Apg.decrypt(this, in, out, size, Apg.getCachedPassPhrase(getSecretKeyId()),
+ data = Apg.decrypt(this, in, out, Apg.getCachedPassPhrase(getSecretKeyId()),
this, mAssumeSymmetricEncryption);
}
out.close();
- if (randomString != null) {
- data.putString(Apg.EXTRA_RESULT_URI, "content://" + DataProvider.AUTHORITY + "/data/" + randomString);
+ if (mDataDestination.getStreamFilename() != null) {
+ data.putString(Apg.EXTRA_RESULT_URI, "content://" + DataProvider.AUTHORITY +
+ "/data/" + mDataDestination.getStreamFilename());
} else if (mDecryptTarget == Id.target.message) {
- data.putString(Apg.EXTRA_DECRYPTED_MESSAGE,
- new String(((ByteArrayOutputStream) out).toByteArray()));
+ if (mReturnBinary) {
+ data.putByteArray(Apg.EXTRA_DECRYPTED_DATA,
+ ((ByteArrayOutputStream) out).toByteArray());
+ } else {
+ data.putString(Apg.EXTRA_DECRYPTED_MESSAGE,
+ new String(((ByteArrayOutputStream) out).toByteArray()));
+ }
}
} catch (PGPException e) {
error = "" + e;
@@ -727,4 +685,31 @@ public class DecryptActivity extends BaseActivity {
return super.onCreateDialog(id);
}
+
+ protected void fillDataSource() {
+ mDataSource = new DataSource();
+ if (mContentUri != null) {
+ mDataSource.setUri(mContentUri);
+ } else if (mDecryptTarget == Id.target.file) {
+ mDataSource.setUri(mInputFilename);
+ } else {
+ if (mData != null) {
+ mDataSource.setData(mData);
+ } else {
+ mDataSource.setText(mMessage.getText().toString());
+ }
+ }
+ }
+
+ protected void fillDataDestination() {
+ mDataDestination = new DataDestination();
+ if (mContentUri != null) {
+ mDataDestination.setMode(Id.mode.stream);
+ } else if (mDecryptTarget == Id.target.file) {
+ mDataDestination.setFilename(mOutputFilename);
+ mDataDestination.setMode(Id.mode.file);
+ } else {
+ mDataDestination.setMode(Id.mode.byte_array);
+ }
+ }
}
diff --git a/src/org/thialfihar/android/apg/EncryptActivity.java b/src/org/thialfihar/android/apg/EncryptActivity.java
index f4fa6ae74..4854f355c 100644
--- a/src/org/thialfihar/android/apg/EncryptActivity.java
+++ b/src/org/thialfihar/android/apg/EncryptActivity.java
@@ -16,13 +16,9 @@
package org.thialfihar.android.apg;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@@ -34,8 +30,6 @@ import org.bouncycastle2.openpgp.PGPPublicKey;
import org.bouncycastle2.openpgp.PGPPublicKeyRing;
import org.bouncycastle2.openpgp.PGPSecretKey;
import org.bouncycastle2.openpgp.PGPSecretKeyRing;
-import org.bouncycastle2.util.Strings;
-import org.thialfihar.android.apg.Apg.GeneralException;
import org.thialfihar.android.apg.utils.Choice;
import android.app.Dialog;
@@ -43,7 +37,6 @@ import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Message;
import android.text.ClipboardManager;
import android.view.View;
@@ -100,6 +93,14 @@ public class EncryptActivity extends BaseActivity {
private String mInputFilename = null;
private String mOutputFilename = null;
+ private boolean mAsciiArmourDemand = false;
+ private boolean mOverrideAsciiArmour = false;
+ private Uri mContentUri = null;
+ private byte[] mData = null;
+
+ private DataSource mDataSource = null;
+ private DataDestination mDataDestination = null;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -271,6 +272,7 @@ public class EncryptActivity extends BaseActivity {
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction()) ||
Apg.Intent.ENCRYPT_FILE.equals(mIntent.getAction()) ||
Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction())) {
+ mContentUri = mIntent.getData();
Bundle extras = mIntent.getExtras();
if (extras == null) {
extras = new Bundle();
@@ -280,7 +282,17 @@ public class EncryptActivity extends BaseActivity {
mReturnResult = true;
}
- String data = extras.getString(Apg.EXTRA_TEXT);
+ if (extras.containsKey(Apg.EXTRA_ASCII_ARMOUR)) {
+ mAsciiArmourDemand = extras.getBoolean(Apg.EXTRA_ASCII_ARMOUR, true);
+ mOverrideAsciiArmour = true;
+ mAsciiArmour.setChecked(mAsciiArmourDemand);
+ }
+
+ mData = extras.getByteArray(Apg.EXTRA_DATA);
+ String textData = null;
+ if (mData == null) {
+ textData = extras.getString(Apg.EXTRA_TEXT);
+ }
mSendTo = extras.getString(Apg.EXTRA_SEND_TO);
mSubject = extras.getString(Apg.EXTRA_SUBJECT);
long signatureKeyId = extras.getLong(Apg.EXTRA_SIGNATURE_KEY_ID);
@@ -327,8 +339,8 @@ public class EncryptActivity extends BaseActivity {
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction()) ||
Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction())) {
- if (data != null) {
- mMessage.setText(data);
+ if (textData != null) {
+ mMessage.setText(textData);
}
mSource.setInAnimation(null);
mSource.setOutAnimation(null);
@@ -548,11 +560,11 @@ public class EncryptActivity extends BaseActivity {
String error = null;
Bundle data = new Bundle();
Message msg = new Message();
-
+ fillDataSource();
+ fillDataDestination();
try {
- InputStream in;
+ InputData in;
OutputStream out;
- long size;
boolean useAsciiArmour = true;
long encryptionKeyIds[] = null;
long signatureKeyId = 0;
@@ -571,65 +583,28 @@ public class EncryptActivity extends BaseActivity {
signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0);
}
- if (mEncryptTarget == Id.target.file) {
- if (mInputFilename.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath()) ||
- mOutputFilename.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- throw new GeneralException(getString(R.string.error_externalStorageNotReady));
- }
- }
-
- if (mInputFilename.startsWith("content")) {
- in = getContentResolver().openInputStream(Uri.parse(mInputFilename));
- size = 0;
- long n = 0;
- byte dummy[] = new byte[0x10000];
- while ((n = in.read(dummy)) > 0) {
- size += n;
- }
- in = getContentResolver().openInputStream(Uri.parse(mInputFilename));
- } else {
- in = new FileInputStream(mInputFilename);
- File file = new File(mInputFilename);
- size = file.length();
- }
- out = new FileOutputStream(mOutputFilename);
+ // streams
+ in = mDataSource.getInputData(this, true);
+ out = mDataDestination.getOutputStream(this);
+ if (mEncryptTarget == Id.target.file) {
useAsciiArmour = mAsciiArmour.isChecked();
compressionId = ((Choice) mFileCompression.getSelectedItem()).getId();
} else {
- String message = mMessage.getText().toString();
-
- if (signOnly && !mReturnResult) {
- // fix the message a bit, trailing spaces and newlines break stuff,
- // because GMail sends as HTML and such things fuck up the signature,
- // TODO: things like "<" and ">" also fuck up the signature
- message = message.replaceAll(" +\n", "\n");
- message = message.replaceAll("\n\n+", "\n\n");
- message = message.replaceFirst("^\n+", "");
- // make sure there'll be exactly one newline at the end
- message = message.replaceFirst("\n*$", "\n");
- }
-
- if (signOnly && !message.endsWith("\n")) {
- message += '\n';
- }
-
- byte[] byteData = Strings.toUTF8ByteArray(message);
- in = new ByteArrayInputStream(byteData);
- out = new ByteArrayOutputStream();
-
- size = byteData.length;
useAsciiArmour = true;
compressionId = mPreferences.getDefaultMessageCompression();
}
+ if (mOverrideAsciiArmour) {
+ useAsciiArmour = mAsciiArmourDemand;
+ }
+
if (signOnly) {
Apg.signText(this, in, out, getSecretKeyId(),
Apg.getCachedPassPhrase(getSecretKeyId()),
mPreferences.getDefaultHashAlgorithm(), this);
} else {
- Apg.encrypt(this, in, out, size, useAsciiArmour,
+ Apg.encrypt(this, in, out, useAsciiArmour,
encryptionKeyIds, signatureKeyId,
Apg.getCachedPassPhrase(signatureKeyId), this,
mPreferences.getDefaultEncryptionAlgorithm(),
@@ -639,8 +614,13 @@ public class EncryptActivity extends BaseActivity {
out.close();
if (mEncryptTarget != Id.target.file) {
- data.putString(Apg.EXTRA_ENCRYPTED_MESSAGE,
- new String(((ByteArrayOutputStream)out).toByteArray()));
+ if (useAsciiArmour) {
+ data.putString(Apg.EXTRA_ENCRYPTED_MESSAGE,
+ new String(((ByteArrayOutputStream)out).toByteArray()));
+ } else {
+ data.putByteArray(Apg.EXTRA_ENCRYPTED_DATA,
+ ((ByteArrayOutputStream)out).toByteArray());
+ }
}
} catch (IOException e) {
error = "" + e;
@@ -889,4 +869,31 @@ public class EncryptActivity extends BaseActivity {
return super.onCreateDialog(id);
}
+
+ protected void fillDataSource() {
+ mDataSource = new DataSource();
+ if (mContentUri != null) {
+ mDataSource.setUri(mContentUri);
+ } else if (mEncryptTarget == Id.target.file) {
+ mDataSource.setUri(mInputFilename);
+ } else {
+ if (mData != null) {
+ mDataSource.setData(mData);
+ } else {
+ mDataSource.setText(mMessage.getText().toString());
+ }
+ }
+ }
+
+ protected void fillDataDestination() {
+ mDataDestination = new DataDestination();
+ if (mContentUri != null) {
+ mDataDestination.setMode(Id.mode.stream);
+ } else if (mEncryptTarget == Id.target.file) {
+ mDataDestination.setFilename(mOutputFilename);
+ mDataDestination.setMode(Id.mode.file);
+ } else {
+ mDataDestination.setMode(Id.mode.byte_array);
+ }
+ }
} \ No newline at end of file
diff --git a/src/org/thialfihar/android/apg/GeneralActivity.java b/src/org/thialfihar/android/apg/GeneralActivity.java
index 686d6fd39..49cbdcf2a 100644
--- a/src/org/thialfihar/android/apg/GeneralActivity.java
+++ b/src/org/thialfihar/android/apg/GeneralActivity.java
@@ -14,11 +14,11 @@ import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
-import android.widget.AdapterView.OnItemClickListener;
public class GeneralActivity extends BaseActivity {
private Intent mIntent;
diff --git a/src/org/thialfihar/android/apg/Id.java b/src/org/thialfihar/android/apg/Id.java
index 69966e2ff..bc8b7e443 100644
--- a/src/org/thialfihar/android/apg/Id.java
+++ b/src/org/thialfihar/android/apg/Id.java
@@ -135,6 +135,13 @@ public final class Id {
public static final int message = 0x21070004;
}
+ public static final class mode {
+ public static final int undefined = 0x21070001;
+ public static final int byte_array = 0x21070002;
+ public static final int file = 0x21070003;
+ public static final int stream = 0x21070004;
+ }
+
public static final class key {
public static final int none = 0;
public static final int symmetric = -1;
diff --git a/src/org/thialfihar/android/apg/InputData.java b/src/org/thialfihar/android/apg/InputData.java
new file mode 100644
index 000000000..cf49f1c33
--- /dev/null
+++ b/src/org/thialfihar/android/apg/InputData.java
@@ -0,0 +1,25 @@
+package org.thialfihar.android.apg;
+
+import java.io.InputStream;
+
+public class InputData {
+ private PositionAwareInputStream mInputStream;
+ private long mSize;
+
+ InputData(InputStream inputStream, long size) {
+ mInputStream = new PositionAwareInputStream(inputStream);
+ mSize = size;
+ }
+
+ public InputStream getInputStream() {
+ return mInputStream;
+ }
+
+ public long getSize() {
+ return mSize;
+ }
+
+ public long getStreamPosition() {
+ return mInputStream.position();
+ }
+}
diff --git a/src/org/thialfihar/android/apg/KeyListActivity.java b/src/org/thialfihar/android/apg/KeyListActivity.java
index ac861f0ac..26c744f33 100644
--- a/src/org/thialfihar/android/apg/KeyListActivity.java
+++ b/src/org/thialfihar/android/apg/KeyListActivity.java
@@ -48,15 +48,15 @@ import android.os.Message;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.ExpandableListView;
+import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
-import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
public class KeyListActivity extends BaseActivity {
protected ExpandableListView mList;
@@ -328,7 +328,7 @@ public class KeyListActivity extends BaseActivity {
}
if (mTask == Id.task.import_keys) {
- data = Apg.importKeyRings(this, mKeyType, importInputStream, size, this);
+ data = Apg.importKeyRings(this, mKeyType, new InputData(importInputStream, size), this);
} else {
Vector<Integer> keyRingIds = new Vector<Integer>();
if (mSelectedItem == -1) {
diff --git a/src/org/thialfihar/android/apg/MailListActivity.java b/src/org/thialfihar/android/apg/MailListActivity.java
index fb4d39f6a..d78dd47e1 100644
--- a/src/org/thialfihar/android/apg/MailListActivity.java
+++ b/src/org/thialfihar/android/apg/MailListActivity.java
@@ -30,11 +30,11 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
public class MailListActivity extends ListActivity {
LayoutInflater mInflater = null;
diff --git a/src/org/thialfihar/android/apg/MainActivity.java b/src/org/thialfihar/android/apg/MainActivity.java
index f103e9548..31ff027d3 100644
--- a/src/org/thialfihar/android/apg/MainActivity.java
+++ b/src/org/thialfihar/android/apg/MainActivity.java
@@ -29,21 +29,21 @@ import android.database.SQLException;
import android.net.Uri;
import android.os.Bundle;
import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
-import android.widget.AdapterView.OnItemClickListener;
public class MainActivity extends BaseActivity {
private ListView mAccounts = null;
diff --git a/src/org/thialfihar/android/apg/PreferencesActivity.java b/src/org/thialfihar/android/apg/PreferencesActivity.java
index 7e89e40a7..7e584a7a6 100644
--- a/src/org/thialfihar/android/apg/PreferencesActivity.java
+++ b/src/org/thialfihar/android/apg/PreferencesActivity.java
@@ -18,7 +18,6 @@ package org.thialfihar.android.apg;
import org.bouncycastle2.bcpg.HashAlgorithmTags;
import org.bouncycastle2.openpgp.PGPEncryptedData;
-import org.thialfihar.android.apg.utils.Choice;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
diff --git a/src/org/thialfihar/android/apg/PublicKeyListActivity.java b/src/org/thialfihar/android/apg/PublicKeyListActivity.java
index 74e964ec8..916d4e6c2 100644
--- a/src/org/thialfihar/android/apg/PublicKeyListActivity.java
+++ b/src/org/thialfihar/android/apg/PublicKeyListActivity.java
@@ -18,9 +18,9 @@ package org.thialfihar.android.apg;
import android.os.Bundle;
import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ExpandableListView;
public class PublicKeyListActivity extends KeyListActivity {
diff --git a/src/org/thialfihar/android/apg/SecretKeyListActivity.java b/src/org/thialfihar/android/apg/SecretKeyListActivity.java
index fb8ad92c6..9ff7f0fa3 100644
--- a/src/org/thialfihar/android/apg/SecretKeyListActivity.java
+++ b/src/org/thialfihar/android/apg/SecretKeyListActivity.java
@@ -20,10 +20,10 @@ import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ExpandableListView.OnChildClickListener;
diff --git a/src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java b/src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java
index c0ab57710..0b18ecc15 100644
--- a/src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java
+++ b/src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java
@@ -23,10 +23,10 @@ import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
public class SelectSecretKeyListActivity extends BaseActivity {
protected ListView mList;