kv = MessageHelper.getKeyValues(message.autocrypt);
for (String key : kv.keySet()) {
String value = kv.get(key);
Log.i("Autocrypt " + key + "=" + value);
if (value == null)
continue;
switch (key) {
case "addr":
addr = value;
break;
case "prefer-encrypt":
mutual = value.trim().toLowerCase(Locale.ROOT).equals("mutual");
break;
case "keydata":
keydata = Base64.decode(value, Base64.DEFAULT);
break;
}
}
if (addr == null)
throw new IllegalArgumentException("Autocrypt: addr not found");
if (!addr.equalsIgnoreCase(peer))
throw new IllegalArgumentException("Autocrypt: addr different from peer");
if (keydata == null)
throw new IllegalArgumentException("Autocrypt: keydata not found");
AutocryptPeerUpdate update = AutocryptPeerUpdate.create(
keydata, new Date(message.received), mutual);
data.putExtra(OpenPgpApi.EXTRA_AUTOCRYPT_PEER_ID, addr);
data.putExtra(OpenPgpApi.EXTRA_AUTOCRYPT_PEER_UPDATE, update);
} catch (Throwable ex) {
Log.w(ex);
}
Intent result;
try {
// Decrypt message
result = PgpHelper.execute(context, data, in, out);
int resultCode = result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
switch (resultCode) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
Integer encrypt = null;
if (out != null)
if (inline) {
try {
db.beginTransaction();
// Write decrypted body
String text = Helper.readText(plain);
String html = "" + HtmlHelper.formatPlainText(text) + "
";
Helper.writeText(message.getFile(context), html);
db.message().setMessageStored(message.id, new Date().getTime());
db.message().setMessageFts(message.id, false);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
WorkerFts.init(context, false);
} else {
// Decode message
MessageHelper.MessageParts parts;
Properties props = MessageHelper.getSessionProperties(true);
Session isession = Session.getInstance(props, null);
MimeMessage imessage;
try (InputStream fis = new FileInputStream(plain)) {
imessage = new MimeMessage(isession, fis);
}
MessageHelper helper = new MessageHelper(imessage, context);
parts = helper.getMessageParts();
String protect_subject = parts.getProtectedSubject();
// Write decrypted body
boolean debug = prefs.getBoolean("debug", false);
boolean download_plain = prefs.getBoolean("download_plain", false);
String html = parts.getHtml(context, download_plain);
if (html == null && debug) {
int textColorLink = Helper.resolveColor(context, android.R.attr.textColorLink);
SpannableStringBuilder ssb = new SpannableStringBuilderEx();
MessageHelper.getStructure(imessage, ssb, 0, textColorLink);
html = HtmlHelper.toHtml(ssb, context);
}
Helper.writeText(message.getFile(context), html);
Log.i("pgp html=" + (html == null ? null : html.length()));
String text = HtmlHelper.getFullText(html);
message.preview = HtmlHelper.getPreview(text);
message.language = HtmlHelper.getLanguage(context, message.subject, text);
try {
db.beginTransaction();
if (protect_subject != null)
db.message().setMessageSubject(message.id, protect_subject);
db.message().setMessageContent(message.id,
true,
message.language,
parts.isPlainOnly(download_plain),
message.preview,
message.warning);
// Remove existing attachments
db.attachment().deleteAttachments(message.id, new int[]{EntityAttachment.PGP_MESSAGE});
// Add decrypted attachments
List remotes = parts.getAttachments();
for (int index = 0; index < remotes.size(); index++) {
EntityAttachment remote = remotes.get(index);
remote.message = message.id;
remote.sequence = index + 1;
remote.id = db.attachment().insertAttachment(remote);
try {
parts.downloadAttachment(context, index, remote, null);
} catch (Throwable ex) {
Log.e(ex);
}
}
checkPep(message, remotes, context);
encrypt = parts.getEncryption();
db.message().setMessageEncrypt(message.id, encrypt);
db.message().setMessageRevision(message.id, 1);
db.message().setMessageStored(message.id, new Date().getTime());
db.message().setMessageFts(message.id, false);
File raw = message.getRawFile(context);
Helper.copy(plain, raw);
db.message().setMessageRaw(message.id, true);
db.setTransactionSuccessful();
} catch (SQLiteConstraintException ex) {
// Message removed
Log.w(ex);
} finally {
db.endTransaction();
}
WorkerFts.init(context, false);
}
// Check signature status
OpenPgpSignatureResult sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
int sresult = (sigResult == null ? RESULT_NO_SIGNATURE : sigResult.getResult());
if (sigResult == null)
Log.w("PGP signature result missing");
else
Log.i("PGP signature result=" + sresult);
if (sresult == RESULT_NO_SIGNATURE) {
if (!EntityAttachment.PGP_SIGNATURE.equals(encrypt))
args.putString("sigresult", context.getString(R.string.title_signature_none));
} else if (sresult == RESULT_VALID_KEY_CONFIRMED || sresult == RESULT_VALID_KEY_UNCONFIRMED) {
List users = sigResult.getConfirmedUserIds();
String text;
if (users.size() > 0)
text = context.getString(sresult == RESULT_VALID_KEY_UNCONFIRMED
? R.string.title_signature_unconfirmed_from
: R.string.title_signature_valid_from,
TextUtils.join(", ", users));
else
text = context.getString(sresult == RESULT_VALID_KEY_UNCONFIRMED
? R.string.title_signature_unconfirmed
: R.string.title_signature_valid);
args.putString("sigresult", text);
if (sresult == RESULT_VALID_KEY_CONFIRMED)
db.message().setMessageVerified(message.id, true);
} else if (sresult == RESULT_KEY_MISSING)
args.putString("sigresult", context.getString(R.string.title_signature_key_missing));
else {
String text = context.getString(R.string.title_signature_invalid_reason, Integer.toString(sresult));
args.putString("sigresult", text);
}
break;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
if (auto)
return null;
return result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
case OpenPgpApi.RESULT_CODE_ERROR:
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
throw new IllegalArgumentException(
"OpenPgp" +
" error " + (error == null ? "?" : error.getErrorId()) +
": " + (error == null ? "?" : error.getMessage()));
default:
throw new IllegalStateException("OpenPgp unknown result code=" + resultCode);
}
} finally {
plain.delete();
}
return null;
}
@Override
protected void onExecuted(Bundle args, PendingIntent pi) {
if (args.containsKey("sigresult")) {
String text = args.getString("sigresult");
Snackbar sb = Snackbar.make(view, text, Snackbar.LENGTH_LONG)
.setGestureInsetBottomIgnored(true);
Helper.setSnackbarLines(sb, 7);
sb.show();
}
if (pi != null)
try {
Log.i("Executing pi=" + pi);
startIntentSenderForResult(
pi.getIntentSender(),
REQUEST_OPENPGP,
null, 0, 0, 0,
Helper.getBackgroundActivityOptions());
} catch (IntentSender.SendIntentException ex) {
// Likely cancelled
Log.w(ex);
}
}
@Override
protected void onException(Bundle args, Throwable ex) {
boolean auto = args.getBoolean("auto");
if (auto)
return;
if (ex instanceof IllegalArgumentException) {
Log.i(ex);
Snackbar.make(view, ex.getMessage(), Snackbar.LENGTH_LONG)
.setGestureInsetBottomIgnored(true).show();
} else if (ex instanceof OperationCanceledException) {
Snackbar snackbar = Snackbar.make(view, R.string.title_no_openpgp, Snackbar.LENGTH_INDEFINITE)
.setGestureInsetBottomIgnored(true);
snackbar.setAction(R.string.title_fix, new View.OnClickListener() {
@Override
public void onClick(View v) {
snackbar.dismiss();
Helper.viewFAQ(v.getContext(), 12);
}
});
snackbar.show();
} else
Log.unexpectedError(getParentFragmentManager(), ex);
}
}.serial().execute(this, args, "decrypt:pgp");
}
private void onSmime(Bundle args) {
new SimpleTask() {
@Override
protected X509Certificate onExecute(Context context, Bundle args) throws Throwable {
long id = args.getLong("id");
int type = args.getInt("type");
DB db = DB.getInstance(context);
EntityMessage message = db.message().getMessage(id);
if (message == null)
return null;
X509Certificate result = null;
if (EntityMessage.SMIME_SIGNONLY.equals(type)) {
// Get content/signature
boolean sdata = false;
File content = null;
File signature = null;
List attachments = db.attachment().getAttachments(message.id);
for (EntityAttachment attachment : attachments)
if (EntityAttachment.SMIME_SIGNATURE.equals(attachment.encryption)) {
if (!attachment.available)
throw new IllegalArgumentException(context.getString(R.string.title_attachments_missing));
signature = attachment.getFile(context);
} else if (EntityAttachment.SMIME_SIGNED_DATA.equals(attachment.encryption)) {
if (!attachment.available)
throw new IllegalArgumentException(context.getString(R.string.title_attachments_missing));
sdata = true;
signature = attachment.getFile(context);
} else if (EntityAttachment.SMIME_CONTENT.equals(attachment.encryption)) {
if (!attachment.available)
throw new IllegalArgumentException(context.getString(R.string.title_attachments_missing));
content = attachment.getFile(context);
}
if (content == null && !sdata)
throw new IllegalArgumentException("Signed content missing");
if (signature == null)
throw new IllegalArgumentException("Signature missing");
// Build signed data
InputStream is = null;
FileInputStream fis = new FileInputStream(signature);
CMSSignedData signedData;
// TODO: CMSSignedDataParser
if (sdata) {
signedData = new CMSSignedData(fis);
CMSTypedData sc = signedData.getSignedContent();
if (sc == null)
throw new IllegalArgumentException("Signed content missing");
is = new ByteArrayInputStream((byte[]) sc.getContent());
} else {
CMSProcessable signedContent = new CMSProcessableFile(content);
signedData = new CMSSignedData(signedContent, fis);
}
// Check signature
boolean matching = false;
Store store = signedData.getCertificates();
SignerInformationStore signerInfos = signedData.getSignerInfos();
Collection signers = signerInfos.getSigners();
Log.i("Signers count=" + signers.size());
for (SignerInformation signer : signers) {
SignerId sid = signer.getSID();
Log.i("Checking signer=" + (sid == null ? null : sid.getIssuer()));
Collection