mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-23 17:22:16 -05:00
rewrote sign-only code, also finally recognize sign-only emails in the list and allow opening them for verification
This commit is contained in:
parent
acd71a45c0
commit
c212f28c44
@ -25,7 +25,7 @@
|
|||||||
android:layout_width="fill_parent">
|
android:layout_width="fill_parent">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ic_encrypted"
|
android:id="@+id/ic_status"
|
||||||
android:src="@drawable/encrypted"
|
android:src="@drawable/encrypted"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
<string name="btn_send">Send via Email</string>
|
<string name="btn_send">Send via Email</string>
|
||||||
<string name="btn_decrypt">Decrypt</string>
|
<string name="btn_decrypt">Decrypt</string>
|
||||||
|
<string name="btn_verify">Verify</string>
|
||||||
<string name="btn_selectEncryptKeys">Select Recipients</string>
|
<string name="btn_selectEncryptKeys">Select Recipients</string>
|
||||||
<string name="btn_reply">Reply</string>
|
<string name="btn_reply">Reply</string>
|
||||||
<string name="btn_encryptMessage">Encrypt Message</string>
|
<string name="btn_encryptMessage">Encrypt Message</string>
|
||||||
|
@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.thialfihar.android.apg;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -42,6 +44,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.bouncycastle2.bcpg.ArmoredInputStream;
|
||||||
import org.bouncycastle2.bcpg.ArmoredOutputStream;
|
import org.bouncycastle2.bcpg.ArmoredOutputStream;
|
||||||
import org.bouncycastle2.bcpg.BCPGOutputStream;
|
import org.bouncycastle2.bcpg.BCPGOutputStream;
|
||||||
import org.bouncycastle2.bcpg.CompressionAlgorithmTags;
|
import org.bouncycastle2.bcpg.CompressionAlgorithmTags;
|
||||||
@ -125,6 +128,10 @@ public class Apg {
|
|||||||
Pattern.compile(".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
|
Pattern.compile(".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
|
||||||
Pattern.DOTALL);
|
Pattern.DOTALL);
|
||||||
|
|
||||||
|
public static Pattern PGP_SIGNED_MESSAGE =
|
||||||
|
Pattern.compile(".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
|
||||||
|
Pattern.DOTALL);
|
||||||
|
|
||||||
protected static boolean mInitialized = false;
|
protected static boolean mInitialized = false;
|
||||||
|
|
||||||
protected static final int RETURN_NO_MASTER_KEY = -2;
|
protected static final int RETURN_NO_MASTER_KEY = -2;
|
||||||
@ -1247,17 +1254,16 @@ public class Apg {
|
|||||||
progress.setProgress("done.", 100, 100);
|
progress.setProgress("done.", 100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sign(InputStream inStream, OutputStream outStream,
|
public static void signText(InputStream inStream, OutputStream outStream,
|
||||||
long signatureKeyId, String signaturePassPhrase,
|
long signatureKeyId, String signaturePassPhrase,
|
||||||
ProgressDialogUpdater progress)
|
int hashAlgorithm,
|
||||||
|
ProgressDialogUpdater progress)
|
||||||
throws GeneralException, PGPException, IOException, NoSuchAlgorithmException,
|
throws GeneralException, PGPException, IOException, NoSuchAlgorithmException,
|
||||||
SignatureException {
|
SignatureException {
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
|
||||||
ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream);
|
ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream);
|
||||||
armorOut.setHeader("Version", FULL_VERSION);
|
armorOut.setHeader("Version", FULL_VERSION);
|
||||||
OutputStream out = armorOut;
|
|
||||||
OutputStream signOut = out;
|
|
||||||
|
|
||||||
PGPSecretKey signingKey = null;
|
PGPSecretKey signingKey = null;
|
||||||
PGPSecretKeyRing signingKeyRing = null;
|
PGPSecretKeyRing signingKeyRing = null;
|
||||||
@ -1286,7 +1292,7 @@ public class Apg {
|
|||||||
progress.setProgress("preparing signature...", 30, 100);
|
progress.setProgress("preparing signature...", 30, 100);
|
||||||
signatureGenerator =
|
signatureGenerator =
|
||||||
new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
|
new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
|
||||||
HashAlgorithmTags.SHA1,
|
hashAlgorithm,
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
signatureGenerator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
|
signatureGenerator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
|
||||||
String userId = getMainUserId(getMasterKey(signingKeyRing));
|
String userId = getMainUserId(getMasterKey(signingKeyRing));
|
||||||
@ -1296,15 +1302,31 @@ public class Apg {
|
|||||||
signatureGenerator.setHashedSubpackets(spGen.generate());
|
signatureGenerator.setHashedSubpackets(spGen.generate());
|
||||||
|
|
||||||
progress.setProgress("signing...", 40, 100);
|
progress.setProgress("signing...", 40, 100);
|
||||||
int n = 0;
|
|
||||||
byte[] buffer = new byte[1 << 16];
|
armorOut.beginClearText(hashAlgorithm);
|
||||||
while ((n = inStream.read(buffer)) > 0) {
|
|
||||||
signatureGenerator.update(buffer, 0, n);
|
ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
|
||||||
|
int lookAhead = readInputLine(lineOut, inStream);
|
||||||
|
|
||||||
|
processLine(armorOut, signatureGenerator, lineOut.toByteArray());
|
||||||
|
|
||||||
|
if (lookAhead != -1) {
|
||||||
|
do {
|
||||||
|
lookAhead = readInputLine(lineOut, lookAhead, inStream);
|
||||||
|
|
||||||
|
signatureGenerator.update((byte)'\r');
|
||||||
|
signatureGenerator.update((byte)'\n');
|
||||||
|
|
||||||
|
processLine(armorOut, signatureGenerator, lineOut.toByteArray());
|
||||||
|
}
|
||||||
|
while (lookAhead != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
signatureGenerator.generate().encode(signOut);
|
armorOut.endClearText();
|
||||||
signOut.close();
|
|
||||||
out.close();
|
BCPGOutputStream bOut = new BCPGOutputStream(armorOut);
|
||||||
|
signatureGenerator.generate().encode(bOut);
|
||||||
|
armorOut.close();
|
||||||
|
|
||||||
progress.setProgress("done.", 100, 100);
|
progress.setProgress("done.", 100, 100);
|
||||||
}
|
}
|
||||||
@ -1492,6 +1514,108 @@ public class Apg {
|
|||||||
return returnData;
|
return returnData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Bundle verifyText(InputStream inStream, OutputStream outStream,
|
||||||
|
ProgressDialogUpdater progress)
|
||||||
|
throws IOException, GeneralException, PGPException, SignatureException {
|
||||||
|
Bundle returnData = new Bundle();
|
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ArmoredInputStream aIn = new ArmoredInputStream(inStream);
|
||||||
|
|
||||||
|
progress.setProgress("reading data...", 0, 100);
|
||||||
|
|
||||||
|
// mostly taken from CLearSignedFileProcessor
|
||||||
|
ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
|
||||||
|
int lookAhead = readInputLine(lineOut, aIn);
|
||||||
|
byte[] lineSep = getLineSeparator();
|
||||||
|
|
||||||
|
if (lookAhead != -1 && aIn.isClearText())
|
||||||
|
{
|
||||||
|
byte[] line = lineOut.toByteArray();
|
||||||
|
out.write(line, 0, getLengthWithoutSeparator(line));
|
||||||
|
out.write(lineSep);
|
||||||
|
|
||||||
|
while (lookAhead != -1 && aIn.isClearText())
|
||||||
|
{
|
||||||
|
lookAhead = readInputLine(lineOut, lookAhead, aIn);
|
||||||
|
|
||||||
|
line = lineOut.toByteArray();
|
||||||
|
out.write(line, 0, getLengthWithoutSeparator(line));
|
||||||
|
out.write(lineSep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
byte[] clearText = out.toByteArray();
|
||||||
|
outStream.write(clearText);
|
||||||
|
|
||||||
|
returnData.putBoolean("signature", true);
|
||||||
|
|
||||||
|
progress.setProgress("processing signature...", 60, 100);
|
||||||
|
PGPObjectFactory pgpFact = new PGPObjectFactory(aIn);
|
||||||
|
|
||||||
|
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
|
||||||
|
if (sigList == null) {
|
||||||
|
throw new GeneralException("corrupt data");
|
||||||
|
}
|
||||||
|
PGPSignature signature = null;
|
||||||
|
long signatureKeyId = 0;
|
||||||
|
PGPPublicKey signatureKey = null;
|
||||||
|
for (int i = 0; i < sigList.size(); ++i) {
|
||||||
|
signature = sigList.get(i);
|
||||||
|
signatureKey = findPublicKey(signature.getKeyID());
|
||||||
|
if (signatureKeyId == 0) {
|
||||||
|
signatureKeyId = signature.getKeyID();
|
||||||
|
}
|
||||||
|
if (signatureKey == null) {
|
||||||
|
signature = null;
|
||||||
|
} else {
|
||||||
|
signatureKeyId = signature.getKeyID();
|
||||||
|
String userId = null;
|
||||||
|
PGPPublicKeyRing sigKeyRing = findPublicKeyRing(signatureKeyId);
|
||||||
|
if (sigKeyRing != null) {
|
||||||
|
userId = getMainUserId(getMasterKey(sigKeyRing));
|
||||||
|
}
|
||||||
|
returnData.putString("signatureUserId", userId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
returnData.putLong("signatureKeyId", signatureKeyId);
|
||||||
|
|
||||||
|
if (signature == null) {
|
||||||
|
returnData.putBoolean("signatureUnknown", true);
|
||||||
|
progress.setProgress("done.", 100, 100);
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
signature.initVerify(signatureKey, new BouncyCastleProvider());
|
||||||
|
|
||||||
|
InputStream sigIn = new BufferedInputStream(new ByteArrayInputStream(clearText));
|
||||||
|
|
||||||
|
lookAhead = readInputLine(lineOut, sigIn);
|
||||||
|
|
||||||
|
processLine(signature, lineOut.toByteArray());
|
||||||
|
|
||||||
|
if (lookAhead != -1) {
|
||||||
|
do {
|
||||||
|
lookAhead = readInputLine(lineOut, lookAhead, sigIn);
|
||||||
|
|
||||||
|
signature.update((byte)'\r');
|
||||||
|
signature.update((byte)'\n');
|
||||||
|
|
||||||
|
processLine(signature, lineOut.toByteArray());
|
||||||
|
}
|
||||||
|
while (lookAhead != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
returnData.putBoolean("signatureSuccess", signature.verify());
|
||||||
|
|
||||||
|
progress.setProgress("done.", 100, 100);
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
|
||||||
public static Vector<PGPPublicKeyRing> getPublicKeyRings() {
|
public static Vector<PGPPublicKeyRing> getPublicKeyRings() {
|
||||||
return mPublicKeyRings;
|
return mPublicKeyRings;
|
||||||
}
|
}
|
||||||
@ -1499,4 +1623,120 @@ public class Apg {
|
|||||||
public static Vector<PGPSecretKeyRing> getSecretKeyRings() {
|
public static Vector<PGPSecretKeyRing> getSecretKeyRings() {
|
||||||
return mSecretKeyRings;
|
return mSecretKeyRings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// taken from ClearSignedFileProcessor in BC
|
||||||
|
private static int readInputLine(ByteArrayOutputStream bOut, InputStream fIn)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
bOut.reset();
|
||||||
|
|
||||||
|
int lookAhead = -1;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
while ((ch = fIn.read()) >= 0)
|
||||||
|
{
|
||||||
|
bOut.write(ch);
|
||||||
|
if (ch == '\r' || ch == '\n')
|
||||||
|
{
|
||||||
|
lookAhead = readPassedEOL(bOut, ch, fIn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookAhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readInputLine(ByteArrayOutputStream bOut, int lookAhead, InputStream fIn)
|
||||||
|
throws IOException {
|
||||||
|
bOut.reset();
|
||||||
|
|
||||||
|
int ch = lookAhead;
|
||||||
|
|
||||||
|
do {
|
||||||
|
bOut.write(ch);
|
||||||
|
if (ch == '\r' || ch == '\n') {
|
||||||
|
lookAhead = readPassedEOL(bOut, ch, fIn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((ch = fIn.read()) >= 0);
|
||||||
|
|
||||||
|
if (ch < 0) {
|
||||||
|
lookAhead = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookAhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readPassedEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn)
|
||||||
|
throws IOException {
|
||||||
|
int lookAhead = fIn.read();
|
||||||
|
|
||||||
|
if (lastCh == '\r' && lookAhead == '\n') {
|
||||||
|
bOut.write(lookAhead);
|
||||||
|
lookAhead = fIn.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookAhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void processLine(PGPSignature sig, byte[] line)
|
||||||
|
throws SignatureException, IOException {
|
||||||
|
int length = getLengthWithoutWhiteSpace(line);
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
sig.update(line, 0, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void processLine(OutputStream aOut, PGPSignatureGenerator sGen, byte[] line)
|
||||||
|
throws SignatureException, IOException {
|
||||||
|
int length = getLengthWithoutWhiteSpace(line);
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
sGen.update(line, 0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
aOut.write(line, 0, line.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getLengthWithoutSeparator(byte[] line) {
|
||||||
|
int end = line.length - 1;
|
||||||
|
|
||||||
|
while (end >= 0 && isLineEnding(line[end])) {
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isLineEnding(byte b) {
|
||||||
|
return b == '\r' || b == '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getLengthWithoutWhiteSpace(byte[] line) {
|
||||||
|
int end = line.length - 1;
|
||||||
|
|
||||||
|
while (end >= 0 && isWhiteSpace(line[end])) {
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isWhiteSpace(byte b) {
|
||||||
|
return b == '\r' || b == '\n' || b == '\t' || b == ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] getLineSeparator() {
|
||||||
|
String nl = System.getProperty("line.separator");
|
||||||
|
byte[] nlBytes = new byte[nl.length()];
|
||||||
|
|
||||||
|
for (int i = 0; i != nlBytes.length; i++) {
|
||||||
|
nlBytes[i] = (byte)nl.charAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nlBytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ public class DecryptMessageActivity extends Activity
|
|||||||
|
|
||||||
private String mReplyTo = null;
|
private String mReplyTo = null;
|
||||||
private String mSubject = null;
|
private String mSubject = null;
|
||||||
|
private boolean mSignedOnly = false;
|
||||||
|
|
||||||
private ProgressDialog mProgressDialog = null;
|
private ProgressDialog mProgressDialog = null;
|
||||||
private Thread mRunningThread = null;
|
private Thread mRunningThread = null;
|
||||||
@ -193,6 +194,15 @@ public class DecryptMessageActivity extends Activity
|
|||||||
// replace non breakable spaces
|
// replace non breakable spaces
|
||||||
data = data.replaceAll("\\xa0", " ");
|
data = data.replaceAll("\\xa0", " ");
|
||||||
mMessage.setText(data);
|
mMessage.setText(data);
|
||||||
|
} else {
|
||||||
|
matcher = Apg.PGP_SIGNED_MESSAGE.matcher(data);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
data = matcher.group(1);
|
||||||
|
// replace non breakable spaces
|
||||||
|
data = data.replaceAll("\\xa0", " ");
|
||||||
|
mMessage.setText(data);
|
||||||
|
mDecryptButton.setText(R.string.btn_verify);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mReplyTo = intent.getExtras().getString("replyTo");
|
mReplyTo = intent.getExtras().getString("replyTo");
|
||||||
@ -266,8 +276,18 @@ public class DecryptMessageActivity extends Activity
|
|||||||
|
|
||||||
private void decryptClicked() {
|
private void decryptClicked() {
|
||||||
String error = null;
|
String error = null;
|
||||||
|
String messageData = mMessage.getText().toString();
|
||||||
|
Matcher matcher = Apg.PGP_SIGNED_MESSAGE.matcher(messageData);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
mSignedOnly = true;
|
||||||
|
decryptStart();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// else treat it as an encrypted message
|
||||||
|
mSignedOnly = false;
|
||||||
ByteArrayInputStream in =
|
ByteArrayInputStream in =
|
||||||
new ByteArrayInputStream(mMessage.getText().toString().getBytes());
|
new ByteArrayInputStream(messageData.getBytes());
|
||||||
try {
|
try {
|
||||||
mDecryptionKeyId = Apg.getDecryptionKeyId(in);
|
mDecryptionKeyId = Apg.getDecryptionKeyId(in);
|
||||||
showDialog(AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE);
|
showDialog(AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE);
|
||||||
@ -320,7 +340,11 @@ public class DecryptMessageActivity extends Activity
|
|||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
data = Apg.decrypt(in, out, Apg.getPassPhrase(), this);
|
if (mSignedOnly) {
|
||||||
|
data = Apg.verifyText(in, out, this);
|
||||||
|
} else {
|
||||||
|
data = Apg.decrypt(in, out, Apg.getPassPhrase(), this);
|
||||||
|
}
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
error = e.getMessage();
|
error = e.getMessage();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -24,6 +24,7 @@ import java.security.NoSuchProviderException;
|
|||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.bouncycastle2.bcpg.HashAlgorithmTags;
|
||||||
import org.bouncycastle2.openpgp.PGPException;
|
import org.bouncycastle2.openpgp.PGPException;
|
||||||
import org.bouncycastle2.openpgp.PGPPublicKey;
|
import org.bouncycastle2.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle2.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle2.openpgp.PGPPublicKeyRing;
|
||||||
@ -104,16 +105,9 @@ public class EncryptMessageActivity extends Activity
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
String message = data.getString("message");
|
String message = data.getString("message");
|
||||||
String signature = data.getString("signature");
|
|
||||||
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
|
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
|
||||||
emailIntent.setType("text/plain; charset=utf-8");
|
emailIntent.setType("text/plain; charset=utf-8");
|
||||||
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
|
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
|
||||||
if (signature != null) {
|
|
||||||
String fullText = "-----BEGIN PGP SIGNED MESSAGE-----\n" +
|
|
||||||
"Hash: SHA256\n" + "\n" +
|
|
||||||
message + "\n" + signature;
|
|
||||||
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, fullText);
|
|
||||||
}
|
|
||||||
if (mSubject != null) {
|
if (mSubject != null) {
|
||||||
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
|
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
|
||||||
mSubject);
|
mSubject);
|
||||||
@ -305,7 +299,9 @@ public class EncryptMessageActivity extends Activity
|
|||||||
message = message.replaceAll(" +\n", "\n");
|
message = message.replaceAll(" +\n", "\n");
|
||||||
message = message.replaceAll("\n\n+", "\n\n");
|
message = message.replaceAll("\n\n+", "\n\n");
|
||||||
message = message.replaceFirst("^\n+", "");
|
message = message.replaceFirst("^\n+", "");
|
||||||
message = message.replaceFirst("\n+$", "");
|
// make sure there'll be exactly one newline at the end
|
||||||
|
message = message.replaceFirst("\n*$", "\n");
|
||||||
|
|
||||||
ByteArrayInputStream in =
|
ByteArrayInputStream in =
|
||||||
new ByteArrayInputStream(Strings.toUTF8ByteArray(message));
|
new ByteArrayInputStream(Strings.toUTF8ByteArray(message));
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
@ -316,9 +312,9 @@ public class EncryptMessageActivity extends Activity
|
|||||||
Apg.getPassPhrase(), this);
|
Apg.getPassPhrase(), this);
|
||||||
data.putString("message", new String(out.toByteArray()));
|
data.putString("message", new String(out.toByteArray()));
|
||||||
} else {
|
} else {
|
||||||
Apg.sign(in, out, mSignatureKeyId, Apg.getPassPhrase(), this);
|
Apg.signText(in, out, mSignatureKeyId,
|
||||||
data.putString("message", message);
|
Apg.getPassPhrase(), HashAlgorithmTags.SHA256, this);
|
||||||
data.putString("signature", new String(out.toByteArray()));
|
data.putString("message", new String(out.toByteArray()));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
error = e.getMessage();
|
error = e.getMessage();
|
||||||
|
@ -57,9 +57,11 @@ public class MailListActivity extends ListActivity {
|
|||||||
public String fromAddress;
|
public String fromAddress;
|
||||||
public String data;
|
public String data;
|
||||||
public String replyTo;
|
public String replyTo;
|
||||||
|
public boolean signedOnly;
|
||||||
|
|
||||||
public Message(Conversation parent, long id, String subject,
|
public Message(Conversation parent, long id, String subject,
|
||||||
String fromAddress, String replyTo, String data) {
|
String fromAddress, String replyTo,
|
||||||
|
String data, boolean signedOnly) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.subject = subject;
|
this.subject = subject;
|
||||||
@ -69,6 +71,7 @@ public class MailListActivity extends ListActivity {
|
|||||||
if (this.replyTo == null || this.replyTo.equals("")) {
|
if (this.replyTo == null || this.replyTo.equals("")) {
|
||||||
this.replyTo = this.fromAddress;
|
this.replyTo = this.fromAddress;
|
||||||
}
|
}
|
||||||
|
this.signedOnly = signedOnly;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,18 +118,26 @@ public class MailListActivity extends ListActivity {
|
|||||||
int bodyIndex = messageCursor.getColumnIndex("body");
|
int bodyIndex = messageCursor.getColumnIndex("body");
|
||||||
String data = messageCursor.getString(bodyIndex);
|
String data = messageCursor.getString(bodyIndex);
|
||||||
data = Html.fromHtml(data).toString();
|
data = Html.fromHtml(data).toString();
|
||||||
|
boolean signedOnly = false;
|
||||||
Matcher matcher = Apg.PGP_MESSAGE.matcher(data);
|
Matcher matcher = Apg.PGP_MESSAGE.matcher(data);
|
||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
data = matcher.group(1);
|
data = matcher.group(1);
|
||||||
} else {
|
} else {
|
||||||
data = null;
|
matcher = Apg.PGP_SIGNED_MESSAGE.matcher(data);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
data = matcher.group(1);
|
||||||
|
signedOnly = true;
|
||||||
|
} else {
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Message message =
|
Message message =
|
||||||
new Message(conversation,
|
new Message(conversation,
|
||||||
messageCursor.getLong(idIndex),
|
messageCursor.getLong(idIndex),
|
||||||
messageCursor.getString(subjectIndex),
|
messageCursor.getString(subjectIndex),
|
||||||
messageCursor.getString(fromAddressIndex),
|
messageCursor.getString(fromAddressIndex),
|
||||||
messageCursor.getString(replyToIndex), data);
|
messageCursor.getString(replyToIndex),
|
||||||
|
data, signedOnly);
|
||||||
|
|
||||||
messages.add(message);
|
messages.add(message);
|
||||||
mmessages.add(message);
|
mmessages.add(message);
|
||||||
@ -186,14 +197,19 @@ public class MailListActivity extends ListActivity {
|
|||||||
|
|
||||||
TextView subject = (TextView) view.findViewById(R.id.subject);
|
TextView subject = (TextView) view.findViewById(R.id.subject);
|
||||||
TextView email = (TextView) view.findViewById(R.id.email_address);
|
TextView email = (TextView) view.findViewById(R.id.email_address);
|
||||||
ImageView encrypted = (ImageView) view.findViewById(R.id.ic_encrypted);
|
ImageView status = (ImageView) view.findViewById(R.id.ic_status);
|
||||||
|
|
||||||
subject.setText(message.subject);
|
subject.setText(message.subject);
|
||||||
email.setText(message.fromAddress);
|
email.setText(message.fromAddress);
|
||||||
if (message.data != null) {
|
if (message.data != null) {
|
||||||
encrypted.setVisibility(View.VISIBLE);
|
if (message.signedOnly) {
|
||||||
|
status.setImageResource(R.drawable.signed);
|
||||||
|
} else {
|
||||||
|
status.setImageResource(R.drawable.encrypted);
|
||||||
|
}
|
||||||
|
status.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
encrypted.setVisibility(View.INVISIBLE);
|
status.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
Loading…
Reference in New Issue
Block a user