|
|
|
@ -131,13 +131,17 @@ import java.util.Properties;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
import javax.mail.Address;
|
|
|
|
|
import javax.mail.BodyPart;
|
|
|
|
|
import javax.mail.MessageRemovedException;
|
|
|
|
|
import javax.mail.Multipart;
|
|
|
|
|
import javax.mail.Part;
|
|
|
|
|
import javax.mail.Session;
|
|
|
|
|
import javax.mail.internet.AddressException;
|
|
|
|
|
import javax.mail.internet.ContentType;
|
|
|
|
|
import javax.mail.internet.InternetAddress;
|
|
|
|
|
import javax.mail.internet.MimeBodyPart;
|
|
|
|
|
import javax.mail.internet.MimeMessage;
|
|
|
|
|
import javax.mail.internet.MimeMultipart;
|
|
|
|
|
import javax.mail.internet.ParseException;
|
|
|
|
|
|
|
|
|
|
import static android.app.Activity.RESULT_CANCELED;
|
|
|
|
@ -188,7 +192,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
|
|
|
|
|
private boolean prefix_once = false;
|
|
|
|
|
private boolean monospaced = false;
|
|
|
|
|
private boolean encrypt = false;
|
|
|
|
|
private Integer encrypt = null;
|
|
|
|
|
private boolean media = true;
|
|
|
|
|
private boolean compact = false;
|
|
|
|
|
private int zoom = 0;
|
|
|
|
@ -205,6 +209,8 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
private String[] pgpUserIds;
|
|
|
|
|
private long[] pgpKeyIds;
|
|
|
|
|
private long pgpSignKeyId;
|
|
|
|
|
private String pgpContent;
|
|
|
|
|
private String pgpContentType;
|
|
|
|
|
|
|
|
|
|
static final int REDUCED_IMAGE_SIZE = 1440; // pixels
|
|
|
|
|
static final int REDUCED_IMAGE_QUALITY = 90; // percent
|
|
|
|
@ -930,14 +936,20 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
int colorEncrypt = Helper.resolveColor(getContext(), R.attr.colorEncrypt);
|
|
|
|
|
ImageButton ib = (ImageButton) menu.findItem(R.id.menu_encrypt).getActionView();
|
|
|
|
|
ib.setEnabled(!busy);
|
|
|
|
|
ib.setImageResource(encrypt ? R.drawable.baseline_lock_24 : R.drawable.baseline_lock_open_24);
|
|
|
|
|
ib.setImageTintList(encrypt ? ColorStateList.valueOf(colorEncrypt) : null);
|
|
|
|
|
ib.setImageResource(EntityMessage.ENCRYPTION_SIGNENCRYPT.equals(encrypt)
|
|
|
|
|
? R.drawable.baseline_lock_24 : R.drawable.baseline_lock_open_24);
|
|
|
|
|
ib.setImageTintList(EntityMessage.ENCRYPTION_SIGNENCRYPT.equals(encrypt)
|
|
|
|
|
? ColorStateList.valueOf(colorEncrypt) : null);
|
|
|
|
|
|
|
|
|
|
menu.findItem(R.id.menu_media).setChecked(media);
|
|
|
|
|
menu.findItem(R.id.menu_compact).setChecked(compact);
|
|
|
|
|
|
|
|
|
|
bottom_navigation.getMenu().findItem(R.id.action_send)
|
|
|
|
|
.setTitle(encrypt ? R.string.title_encrypt : R.string.title_send);
|
|
|
|
|
if (EntityMessage.ENCRYPTION_SIGNONLY.equals(encrypt))
|
|
|
|
|
bottom_navigation.getMenu().findItem(R.id.action_send).setTitle(R.string.title_sign);
|
|
|
|
|
else if (EntityMessage.ENCRYPTION_SIGNENCRYPT.equals(encrypt))
|
|
|
|
|
bottom_navigation.getMenu().findItem(R.id.action_send).setTitle(R.string.title_encrypt);
|
|
|
|
|
else
|
|
|
|
|
bottom_navigation.getMenu().findItem(R.id.action_send).setTitle(R.string.title_send);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -987,21 +999,25 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onMenuEncrypt() {
|
|
|
|
|
encrypt = !encrypt;
|
|
|
|
|
encrypt = (EntityMessage.ENCRYPTION_SIGNENCRYPT.equals(encrypt)
|
|
|
|
|
? EntityMessage.ENCRYPTION_NONE : EntityMessage.ENCRYPTION_SIGNENCRYPT);
|
|
|
|
|
getActivity().invalidateOptionsMenu();
|
|
|
|
|
|
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
|
args.putLong("id", working);
|
|
|
|
|
args.putBoolean("encrypt", encrypt);
|
|
|
|
|
args.putInt("encrypt", encrypt);
|
|
|
|
|
|
|
|
|
|
new SimpleTask<Void>() {
|
|
|
|
|
@Override
|
|
|
|
|
protected Void onExecute(Context context, Bundle args) {
|
|
|
|
|
long id = args.getLong("id");
|
|
|
|
|
boolean encrypt = args.getBoolean("encrypt");
|
|
|
|
|
int encrypt = args.getInt("encrypt");
|
|
|
|
|
|
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
|
db.message().setMessageEncrypt(id, encrypt);
|
|
|
|
|
if (EntityMessage.ENCRYPTION_NONE.equals(encrypt))
|
|
|
|
|
db.message().setMessageEncrypt(id, null);
|
|
|
|
|
else
|
|
|
|
|
db.message().setMessageEncrypt(id, encrypt);
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
@ -1200,9 +1216,17 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
pgpUserIds[i] = recipient.getAddress().toLowerCase(Locale.ROOT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_GET_KEY_IDS);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_USER_IDS, pgpUserIds);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, working);
|
|
|
|
|
Intent intent;
|
|
|
|
|
if (EntityMessage.ENCRYPTION_SIGNONLY.equals(draft.encrypt)) {
|
|
|
|
|
intent = new Intent(OpenPgpApi.ACTION_GET_SIGN_KEY_ID);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, working);
|
|
|
|
|
} else if (EntityMessage.ENCRYPTION_SIGNENCRYPT.equals(draft.encrypt)) {
|
|
|
|
|
intent = new Intent(OpenPgpApi.ACTION_GET_KEY_IDS);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_USER_IDS, pgpUserIds);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, working);
|
|
|
|
|
} else
|
|
|
|
|
throw new IllegalArgumentException("Invalid encrypt=" + draft.encrypt);
|
|
|
|
|
|
|
|
|
|
onPgp(intent);
|
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
|
if (ex instanceof IllegalArgumentException)
|
|
|
|
@ -1479,36 +1503,70 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
|
|
|
|
|
|
// Get data
|
|
|
|
|
EntityMessage message = db.message().getMessage(id);
|
|
|
|
|
if (message == null)
|
|
|
|
|
throw new MessageRemovedException();
|
|
|
|
|
EntityIdentity identity = db.identity().getIdentity(message.identity);
|
|
|
|
|
EntityMessage draft = db.message().getMessage(id);
|
|
|
|
|
if (draft == null)
|
|
|
|
|
throw new MessageRemovedException("PGP");
|
|
|
|
|
EntityIdentity identity = db.identity().getIdentity(draft.identity);
|
|
|
|
|
if (identity == null)
|
|
|
|
|
throw new IllegalArgumentException(getString(R.string.title_from_missing));
|
|
|
|
|
|
|
|
|
|
List<EntityAttachment> attachments = db.attachment().getAttachments(id);
|
|
|
|
|
for (EntityAttachment attachment : new ArrayList<>(attachments))
|
|
|
|
|
if (attachment.encryption != null) {
|
|
|
|
|
if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(data.getAction()))
|
|
|
|
|
db.attachment().deleteAttachment(attachment.id);
|
|
|
|
|
attachments.remove(attachment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create files
|
|
|
|
|
File input = new File(context.getCacheDir(), "input." + id);
|
|
|
|
|
File output = new File(context.getCacheDir(), "output." + id);
|
|
|
|
|
|
|
|
|
|
// Serializing messages is NOT reproducible
|
|
|
|
|
if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(data.getAction())) {
|
|
|
|
|
if ((EntityMessage.ENCRYPTION_SIGNONLY.equals(draft.encrypt) &&
|
|
|
|
|
OpenPgpApi.ACTION_GET_SIGN_KEY_ID.equals(data.getAction())) ||
|
|
|
|
|
(EntityMessage.ENCRYPTION_SIGNENCRYPT.equals(draft.encrypt) &&
|
|
|
|
|
OpenPgpApi.ACTION_GET_KEY_IDS.equals(data.getAction()))) {
|
|
|
|
|
// Get attachments
|
|
|
|
|
List<EntityAttachment> attachments = db.attachment().getAttachments(id);
|
|
|
|
|
for (EntityAttachment attachment : new ArrayList<>(attachments))
|
|
|
|
|
if (attachment.encryption != null) {
|
|
|
|
|
db.attachment().deleteAttachment(attachment.id);
|
|
|
|
|
attachments.remove(attachment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build message
|
|
|
|
|
Properties props = MessageHelper.getSessionProperties();
|
|
|
|
|
Session isession = Session.getInstance(props, null);
|
|
|
|
|
MimeMessage imessage = new MimeMessage(isession);
|
|
|
|
|
MessageHelper.build(context, message, attachments, identity, imessage);
|
|
|
|
|
MessageHelper.build(context, draft, attachments, identity, imessage);
|
|
|
|
|
|
|
|
|
|
if (OpenPgpApi.ACTION_GET_SIGN_KEY_ID.equals(data.getAction())) {
|
|
|
|
|
// Serialize content
|
|
|
|
|
imessage.saveChanges();
|
|
|
|
|
Object content = imessage.getContent();
|
|
|
|
|
if (content instanceof String) {
|
|
|
|
|
pgpContent = (String) content;
|
|
|
|
|
pgpContentType = imessage.getContentType();
|
|
|
|
|
|
|
|
|
|
// Build plain text part with headers
|
|
|
|
|
BodyPart plainPart = new MimeBodyPart();
|
|
|
|
|
plainPart.setContent(pgpContent, pgpContentType);
|
|
|
|
|
Multipart plainMultiPart = new MimeMultipart();
|
|
|
|
|
plainMultiPart.addBodyPart(plainPart);
|
|
|
|
|
MimeMessage m = new MimeMessage(isession);
|
|
|
|
|
m.setContent(plainMultiPart);
|
|
|
|
|
m.saveChanges();
|
|
|
|
|
|
|
|
|
|
try (OutputStream out = new FileOutputStream(input)) {
|
|
|
|
|
plainPart.writeTo(out);
|
|
|
|
|
}
|
|
|
|
|
} else if (content instanceof Multipart) {
|
|
|
|
|
pgpContent = null;
|
|
|
|
|
pgpContentType = ((MimeMultipart) content).getContentType();
|
|
|
|
|
|
|
|
|
|
// Serialize message
|
|
|
|
|
try (OutputStream out = new FileOutputStream(input)) {
|
|
|
|
|
imessage.writeTo(out);
|
|
|
|
|
try (OutputStream out = new FileOutputStream(input)) {
|
|
|
|
|
((MimeMultipart) content).writeTo(out);
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
throw new ParseException(content.getClass().getName());
|
|
|
|
|
} else {
|
|
|
|
|
// Serialize message
|
|
|
|
|
try (OutputStream out = new FileOutputStream(input)) {
|
|
|
|
|
imessage.writeTo(out);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1533,6 +1591,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
db.beginTransaction();
|
|
|
|
|
|
|
|
|
|
String name;
|
|
|
|
|
String type = "application/octet-stream";
|
|
|
|
|
int encryption;
|
|
|
|
|
if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction())) {
|
|
|
|
|
name = "keydata.asc";
|
|
|
|
@ -1543,6 +1602,8 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
} else if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(data.getAction())) {
|
|
|
|
|
name = "signature.asc";
|
|
|
|
|
encryption = EntityAttachment.PGP_SIGNATURE;
|
|
|
|
|
type = "application/pgp-signature; micalg=\"" +
|
|
|
|
|
result.getStringExtra(OpenPgpApi.RESULT_SIGNATURE_MICALG) + "\"";
|
|
|
|
|
} else
|
|
|
|
|
throw new IllegalStateException(data.getAction());
|
|
|
|
|
|
|
|
|
@ -1550,7 +1611,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
attachment.message = id;
|
|
|
|
|
attachment.sequence = db.attachment().getAttachmentSequence(id) + 1;
|
|
|
|
|
attachment.name = name;
|
|
|
|
|
attachment.type = "application/octet-stream";
|
|
|
|
|
attachment.type = type;
|
|
|
|
|
attachment.disposition = Part.INLINE;
|
|
|
|
|
attachment.encryption = encryption;
|
|
|
|
|
attachment.id = db.attachment().insertAttachment(attachment);
|
|
|
|
@ -1593,43 +1654,79 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
|
|
|
|
|
if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction()) ||
|
|
|
|
|
(OpenPgpApi.ACTION_GET_KEY_IDS.equals(data.getAction()) && pgpKeyIds.length > 1)) {
|
|
|
|
|
if (identity.sign_key != null) {
|
|
|
|
|
// Encrypt message
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, pgpKeyIds);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, identity.sign_key);
|
|
|
|
|
if (EntityMessage.ENCRYPTION_SIGNONLY.equals(draft.encrypt)) {
|
|
|
|
|
// Sign message
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_DETACHED_SIGN);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, pgpSignKeyId);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, id);
|
|
|
|
|
return intent;
|
|
|
|
|
} else {
|
|
|
|
|
// Get sign key
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_GET_SIGN_KEY_ID);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_USER_IDS, pgpUserIds);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, id);
|
|
|
|
|
return intent;
|
|
|
|
|
if (identity.sign_key != null) {
|
|
|
|
|
// Encrypt message
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, pgpKeyIds);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, identity.sign_key);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, id);
|
|
|
|
|
return intent;
|
|
|
|
|
} else {
|
|
|
|
|
// Get sign key
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_GET_SIGN_KEY_ID);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_USER_IDS, pgpUserIds);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, id);
|
|
|
|
|
return intent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (OpenPgpApi.ACTION_GET_SIGN_KEY_ID.equals(data.getAction())) {
|
|
|
|
|
pgpSignKeyId = result.getLongExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, -1);
|
|
|
|
|
db.identity().setIdentitySignKey(identity.id, pgpSignKeyId);
|
|
|
|
|
|
|
|
|
|
// Encrypt message
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, pgpKeyIds);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, pgpSignKeyId);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, id);
|
|
|
|
|
return intent;
|
|
|
|
|
if (EntityMessage.ENCRYPTION_SIGNONLY.equals(draft.encrypt)) {
|
|
|
|
|
// Get sign key
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_GET_KEY);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_KEY_ID, pgpSignKeyId);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, id);
|
|
|
|
|
return intent;
|
|
|
|
|
} else if (EntityMessage.ENCRYPTION_SIGNENCRYPT.equals(draft.encrypt)) {
|
|
|
|
|
// Encrypt message
|
|
|
|
|
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, pgpKeyIds);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, pgpSignKeyId);
|
|
|
|
|
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
|
|
|
|
intent.putExtra(BuildConfig.APPLICATION_ID, id);
|
|
|
|
|
return intent;
|
|
|
|
|
} else
|
|
|
|
|
throw new IllegalArgumentException("Invalid encrypt=" + draft.encrypt);
|
|
|
|
|
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(data.getAction())) {
|
|
|
|
|
input.delete();
|
|
|
|
|
|
|
|
|
|
// Get signature
|
|
|
|
|
//Intent intent = new Intent(OpenPgpApi.ACTION_DETACHED_SIGN);
|
|
|
|
|
//intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, pgpSignKeyId);
|
|
|
|
|
//intent.putExtra(BuildConfig.APPLICATION_ID, id);
|
|
|
|
|
|
|
|
|
|
// send message
|
|
|
|
|
return null;
|
|
|
|
|
} else if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(data.getAction())) {
|
|
|
|
|
|
|
|
|
|
EntityAttachment attachment = new EntityAttachment();
|
|
|
|
|
attachment.message = id;
|
|
|
|
|
attachment.sequence = db.attachment().getAttachmentSequence(id) + 1;
|
|
|
|
|
attachment.name = "content.txt";
|
|
|
|
|
attachment.type = pgpContentType;
|
|
|
|
|
attachment.disposition = Part.INLINE;
|
|
|
|
|
attachment.encryption = EntityAttachment.PGP_CONTENT;
|
|
|
|
|
attachment.id = db.attachment().insertAttachment(attachment);
|
|
|
|
|
|
|
|
|
|
// Restore plain text without headers
|
|
|
|
|
ContentType ct = new ContentType(pgpContentType);
|
|
|
|
|
if (!"multipart".equals(ct.getPrimaryType()))
|
|
|
|
|
try (OutputStream out = new FileOutputStream(input)) {
|
|
|
|
|
out.write(pgpContent.getBytes());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
File file = attachment.getFile(context);
|
|
|
|
|
input.renameTo(file);
|
|
|
|
|
|
|
|
|
|
db.attachment().setDownloaded(attachment.id, file.length());
|
|
|
|
|
|
|
|
|
|
// send message
|
|
|
|
|
return null;
|
|
|
|
|
} else
|
|
|
|
@ -1845,7 +1942,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onActionSend(EntityMessage draft) {
|
|
|
|
|
if (draft.encrypt != null && draft.encrypt)
|
|
|
|
|
if (draft.encrypt != null && draft.encrypt != 0)
|
|
|
|
|
onEncrypt(draft);
|
|
|
|
|
else
|
|
|
|
|
onAction(R.id.action_send);
|
|
|
|
@ -2135,7 +2232,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
if (plain_only)
|
|
|
|
|
data.draft.plain_only = true;
|
|
|
|
|
if (encrypt_default)
|
|
|
|
|
data.draft.encrypt = true;
|
|
|
|
|
data.draft.encrypt = EntityMessage.ENCRYPTION_SIGNENCRYPT;
|
|
|
|
|
if (receipt_default)
|
|
|
|
|
data.draft.receipt_request = true;
|
|
|
|
|
|
|
|
|
@ -2371,8 +2468,8 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
|
|
|
|
|
if (ref.plain_only != null && ref.plain_only)
|
|
|
|
|
data.draft.plain_only = true;
|
|
|
|
|
if (ref.encrypt != null && ref.encrypt)
|
|
|
|
|
data.draft.encrypt = true;
|
|
|
|
|
if (ref.encrypt != null && ref.encrypt != 0)
|
|
|
|
|
data.draft.encrypt = ref.encrypt;
|
|
|
|
|
|
|
|
|
|
if (answer > 0) {
|
|
|
|
|
EntityAnswer a = db.answer().getAnswer(answer);
|
|
|
|
@ -2558,7 +2655,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data.draft.encrypt == null || !data.draft.encrypt)
|
|
|
|
|
if (data.draft.encrypt == null || data.draft.encrypt == 0)
|
|
|
|
|
EntityOperation.queue(context, data.draft, EntityOperation.ADD);
|
|
|
|
|
} else {
|
|
|
|
|
if (data.draft.revision == null) {
|
|
|
|
@ -2627,7 +2724,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
Log.i("Loaded draft id=" + data.draft.id + " action=" + action);
|
|
|
|
|
|
|
|
|
|
working = data.draft.id;
|
|
|
|
|
encrypt = (data.draft.encrypt != null && data.draft.encrypt);
|
|
|
|
|
encrypt = data.draft.encrypt;
|
|
|
|
|
getActivity().invalidateOptionsMenu();
|
|
|
|
|
|
|
|
|
|
// Show identities
|
|
|
|
@ -2716,7 +2813,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
if (draft == null || draft.ui_hide)
|
|
|
|
|
finish();
|
|
|
|
|
else {
|
|
|
|
|
encrypt = (draft.encrypt != null && draft.encrypt);
|
|
|
|
|
encrypt = draft.encrypt;
|
|
|
|
|
getActivity().invalidateOptionsMenu();
|
|
|
|
|
|
|
|
|
|
Log.i("Draft content=" + draft.content);
|
|
|
|
@ -2864,7 +2961,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
draft.ui_hide = ui_hide;
|
|
|
|
|
db.message().updateMessage(draft);
|
|
|
|
|
|
|
|
|
|
if (draft.content && (draft.encrypt == null || !draft.encrypt))
|
|
|
|
|
if (draft.content && (draft.encrypt == null || draft.encrypt == 0))
|
|
|
|
|
EntityOperation.queue(context, draft, EntityOperation.ADD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3040,7 +3137,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
action == R.id.action_redo ||
|
|
|
|
|
action == R.id.action_check) {
|
|
|
|
|
if (BuildConfig.DEBUG || dirty)
|
|
|
|
|
if (draft.encrypt == null || !draft.encrypt)
|
|
|
|
|
if (draft.encrypt == null || draft.encrypt == 0)
|
|
|
|
|
EntityOperation.queue(context, draft, EntityOperation.ADD);
|
|
|
|
|
|
|
|
|
|
if (action == R.id.action_check) {
|
|
|
|
@ -3602,6 +3699,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
int send_delayed = prefs.getInt("send_delayed", 0);
|
|
|
|
|
boolean send_dialog = prefs.getBoolean("send_dialog", true);
|
|
|
|
|
|
|
|
|
|
final int[] encryptValues = getResources().getIntArray(R.array.encryptValues);
|
|
|
|
|
final int[] sendDelayedValues = getResources().getIntArray(R.array.sendDelayedValues);
|
|
|
|
|
final String[] sendDelayedNames = getResources().getStringArray(R.array.sendDelayedNames);
|
|
|
|
|
|
|
|
|
@ -3612,9 +3710,9 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
final TextView tvTo = dview.findViewById(R.id.tvTo);
|
|
|
|
|
final TextView tvVia = dview.findViewById(R.id.tvVia);
|
|
|
|
|
final CheckBox cbPlainOnly = dview.findViewById(R.id.cbPlainOnly);
|
|
|
|
|
final CheckBox cbEncrypt = dview.findViewById(R.id.cbEncrypt);
|
|
|
|
|
final CheckBox cbReceipt = dview.findViewById(R.id.cbReceipt);
|
|
|
|
|
final TextView tvReceipt = dview.findViewById(R.id.tvReceipt);
|
|
|
|
|
final Spinner spEncrypt = dview.findViewById(R.id.spEncrypt);
|
|
|
|
|
final Spinner spPriority = dview.findViewById(R.id.spPriority);
|
|
|
|
|
final TextView tvSendAt = dview.findViewById(R.id.tvSendAt);
|
|
|
|
|
final ImageButton ibSendAt = dview.findViewById(R.id.ibSendAt);
|
|
|
|
@ -3627,6 +3725,8 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
tvTo.setText(null);
|
|
|
|
|
tvVia.setText(null);
|
|
|
|
|
tvReceipt.setVisibility(View.GONE);
|
|
|
|
|
spEncrypt.setTag(0);
|
|
|
|
|
spEncrypt.setSelection(0);
|
|
|
|
|
spPriority.setTag(1);
|
|
|
|
|
spPriority.setSelection(1);
|
|
|
|
|
tvSendAt.setText(null);
|
|
|
|
@ -3671,21 +3771,23 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
cbEncrypt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
|
|
|
cbReceipt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
|
|
|
|
tvReceipt.setVisibility(checked ? View.VISIBLE : View.GONE);
|
|
|
|
|
|
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
|
args.putLong("id", id);
|
|
|
|
|
args.putBoolean("encrypt", checked);
|
|
|
|
|
args.putBoolean("receipt", checked);
|
|
|
|
|
|
|
|
|
|
new SimpleTask<Void>() {
|
|
|
|
|
@Override
|
|
|
|
|
protected Void onExecute(Context context, Bundle args) {
|
|
|
|
|
long id = args.getLong("id");
|
|
|
|
|
boolean encrypt = args.getBoolean("encrypt");
|
|
|
|
|
boolean receipt = args.getBoolean("receipt");
|
|
|
|
|
|
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
|
db.message().setMessageEncrypt(id, encrypt);
|
|
|
|
|
db.message().setMessageReceiptRequest(id, receipt);
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
@ -3694,27 +3796,39 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
protected void onException(Bundle args, Throwable ex) {
|
|
|
|
|
Helper.unexpectedError(getParentFragmentManager(), ex);
|
|
|
|
|
}
|
|
|
|
|
}.execute(FragmentDialogSend.this, args, "compose:encrypt");
|
|
|
|
|
}.execute(FragmentDialogSend.this, args, "compose:receipt");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
cbReceipt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
|
|
|
spEncrypt.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
|
|
|
|
tvReceipt.setVisibility(checked ? View.VISIBLE : View.GONE);
|
|
|
|
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
|
|
|
int last = (int) spEncrypt.getTag();
|
|
|
|
|
if (last != position) {
|
|
|
|
|
spEncrypt.setTag(position);
|
|
|
|
|
setEncrypt(encryptValues[position]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onNothingSelected(AdapterView<?> parent) {
|
|
|
|
|
spEncrypt.setTag(0);
|
|
|
|
|
setEncrypt(encryptValues[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void setEncrypt(int encrypt) {
|
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
|
args.putLong("id", id);
|
|
|
|
|
args.putBoolean("receipt", checked);
|
|
|
|
|
args.putInt("encrypt", encrypt);
|
|
|
|
|
|
|
|
|
|
new SimpleTask<Void>() {
|
|
|
|
|
@Override
|
|
|
|
|
protected Void onExecute(Context context, Bundle args) {
|
|
|
|
|
long id = args.getLong("id");
|
|
|
|
|
boolean receipt = args.getBoolean("receipt");
|
|
|
|
|
int encrypt = args.getInt("encrypt");
|
|
|
|
|
|
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
|
db.message().setMessageReceiptRequest(id, receipt);
|
|
|
|
|
db.message().setMessageEncrypt(id, encrypt);
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
@ -3723,7 +3837,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
protected void onException(Bundle args, Throwable ex) {
|
|
|
|
|
Helper.unexpectedError(getParentFragmentManager(), ex);
|
|
|
|
|
}
|
|
|
|
|
}.execute(FragmentDialogSend.this, args, "compose:receipt");
|
|
|
|
|
}.execute(FragmentDialogSend.this, args, "compose:encrypt");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -3797,13 +3911,20 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
tvVia.setText(draft.identityEmail);
|
|
|
|
|
|
|
|
|
|
cbPlainOnly.setChecked(draft.plain_only != null && draft.plain_only);
|
|
|
|
|
cbEncrypt.setChecked(draft.encrypt != null && draft.encrypt);
|
|
|
|
|
cbReceipt.setChecked(draft.receipt_request != null && draft.receipt_request);
|
|
|
|
|
|
|
|
|
|
cbPlainOnly.setVisibility(draft.receipt != null && draft.receipt ? View.GONE : View.VISIBLE);
|
|
|
|
|
cbEncrypt.setVisibility(draft.receipt != null && draft.receipt ? View.GONE : View.VISIBLE);
|
|
|
|
|
cbReceipt.setVisibility(draft.receipt != null && draft.receipt ? View.GONE : View.VISIBLE);
|
|
|
|
|
|
|
|
|
|
int encrypt = (draft.encrypt == null ? EntityMessage.ENCRYPTION_NONE : draft.encrypt);
|
|
|
|
|
for (int i = 0; i < encryptValues.length; i++)
|
|
|
|
|
if (encryptValues[i] == encrypt) {
|
|
|
|
|
spEncrypt.setTag(i);
|
|
|
|
|
spEncrypt.setSelection(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
spEncrypt.setVisibility(draft.receipt != null && draft.receipt ? View.GONE : View.VISIBLE);
|
|
|
|
|
|
|
|
|
|
int priority = (draft.priority == null ? 1 : draft.priority);
|
|
|
|
|
spPriority.setTag(priority);
|
|
|
|
|
spPriority.setSelection(priority);
|
|
|
|
|