Support for receiving incoming sync messages.

Closes #3188
// FREEBIE
This commit is contained in:
Moxie Marlinspike
2015-05-18 15:16:27 -07:00
parent 990d858764
commit 2cfc714b64
9 changed files with 207 additions and 88 deletions

View File

@@ -61,13 +61,14 @@ public class EncryptingSmsDatabase extends SmsDatabase {
}
public long insertMessageOutbox(MasterSecret masterSecret, long threadId,
OutgoingTextMessage message, boolean forceSms)
OutgoingTextMessage message, boolean forceSms,
long timestamp)
{
long type = Types.BASE_OUTBOX_TYPE;
message = message.withBody(getEncryptedBody(masterSecret, message.getMessageBody()));
type |= Types.ENCRYPTION_SYMMETRIC_BIT;
return insertMessageOutbox(threadId, message, type, forceSms);
return insertMessageOutbox(threadId, message, type, forceSms, timestamp);
}
public Pair<Long, Long> insertMessageInbox(MasterSecret masterSecret,
@@ -100,10 +101,10 @@ public class EncryptingSmsDatabase extends SmsDatabase {
return insertMessageInbox(message, type);
}
public void updateBundleMessageBody(MasterSecret masterSecret, long messageId, String body) {
public Pair<Long, Long> updateBundleMessageBody(MasterSecret masterSecret, long messageId, String body) {
String encryptedBody = getEncryptedBody(masterSecret, body);
updateMessageBodyAndType(messageId, encryptedBody, Types.TOTAL_MASK,
Types.BASE_INBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT | Types.SECURE_MESSAGE_BIT);
return updateMessageBodyAndType(messageId, encryptedBody, Types.TOTAL_MASK,
Types.BASE_INBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT | Types.SECURE_MESSAGE_BIT);
}
public void updateMessageBody(MasterSecret masterSecret, long messageId, String body) {

View File

@@ -681,7 +681,7 @@ public class MmsDatabase extends MessagingDatabase {
}
public long insertMessageOutbox(MasterSecret masterSecret, OutgoingMediaMessage message,
long threadId, boolean forceSms)
long threadId, boolean forceSms, long timestamp)
throws MmsException
{
long type = Types.BASE_OUTBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT;
@@ -695,7 +695,7 @@ public class MmsDatabase extends MessagingDatabase {
}
SendReq sendRequest = new SendReq();
sendRequest.setDate(System.currentTimeMillis() / 1000L);
sendRequest.setDate(timestamp / 1000L);
sendRequest.setBody(message.getPduBody());
sendRequest.setContentType(ContentType.MULTIPART_MIXED.getBytes());

View File

@@ -303,7 +303,7 @@ public class SmsDatabase extends MessagingDatabase {
database.update(TABLE_NAME, contentValues, null, null);
}
protected void updateMessageBodyAndType(long messageId, String body, long maskOff, long maskOn) {
protected Pair<Long, Long> updateMessageBodyAndType(long messageId, String body, long maskOff, long maskOn) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.execSQL("UPDATE " + TABLE_NAME + " SET " + BODY + " = ?, " +
TYPE + " = (" + TYPE + " & " + (Types.TOTAL_MASK - maskOff) + " | " + maskOn + ") " +
@@ -315,6 +315,8 @@ public class SmsDatabase extends MessagingDatabase {
DatabaseFactory.getThreadDatabase(context).update(threadId);
notifyConversationListeners(threadId);
notifyConversationListListeners();
return new Pair<>(messageId, threadId);
}
public Pair<Long, Long> copyMessageInbox(long messageId) {
@@ -421,15 +423,13 @@ public class SmsDatabase extends MessagingDatabase {
}
protected long insertMessageOutbox(long threadId, OutgoingTextMessage message,
long type, boolean forceSms)
long type, boolean forceSms, long date)
{
if (message.isKeyExchange()) type |= Types.KEY_EXCHANGE_BIT;
else if (message.isSecureMessage()) type |= Types.SECURE_MESSAGE_BIT;
else if (message.isEndSession()) type |= Types.END_SESSION_BIT;
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
long date = System.currentTimeMillis();
ContentValues contentValues = new ContentValues(6);
contentValues.put(ADDRESS, PhoneNumberUtils.formatNumber(message.getRecipients().getPrimaryRecipient().getNumber()));
contentValues.put(THREAD_ID, threadId);

View File

@@ -46,11 +46,6 @@ public class GroupMessageProcessor {
return;
}
if (!message.isSecure()) {
Log.w(TAG, "Received insecure group push action! Ignoring...");
return;
}
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
TextSecureGroup group = message.getGroupInfo().get();
byte[] id = group.getGroupId();

View File

@@ -17,6 +17,8 @@ import org.thoughtcrime.securesms.database.PushDatabase;
import org.thoughtcrime.securesms.groups.GroupMessageProcessor;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
@@ -25,7 +27,9 @@ import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage;
import org.thoughtcrime.securesms.sms.IncomingPreKeyBundleMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.libaxolotl.DuplicateMessageException;
@@ -45,6 +49,8 @@ import org.whispersystems.textsecure.api.crypto.TextSecureCipher;
import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
import org.whispersystems.textsecure.api.messages.TextSecureGroup;
import org.whispersystems.textsecure.api.messages.TextSecureMessage;
import org.whispersystems.textsecure.api.messages.TextSecureSyncContext;
import org.whispersystems.textsecure.api.push.TextSecureAddress;
import java.util.concurrent.TimeUnit;
@@ -81,10 +87,12 @@ public class PushDecryptJob extends MasterSecretJob {
@Override
public void onRun(MasterSecret masterSecret) throws NoSuchMessageException {
PushDatabase database = DatabaseFactory.getPushDatabase(context);
TextSecureEnvelope envelope = database.get(messageId);
PushDatabase database = DatabaseFactory.getPushDatabase(context);
TextSecureEnvelope envelope = database.get(messageId);
Optional<Long> optionalSmsMessageId = smsMessageId > 0 ? Optional.of(smsMessageId) :
Optional.<Long>absent();
handleMessage(masterSecret, envelope, smsMessageId);
handleMessage(masterSecret, envelope, optionalSmsMessageId);
database.delete(messageId);
}
@@ -98,10 +106,11 @@ public class PushDecryptJob extends MasterSecretJob {
}
private void handleMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
private void handleMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
try {
AxolotlStore axolotlStore = new TextSecureAxolotlStore(context, masterSecret);
TextSecureCipher cipher = new TextSecureCipher(axolotlStore);
AxolotlStore axolotlStore = new TextSecureAxolotlStore(context, masterSecret);
TextSecureAddress localAddress = new TextSecureAddress(TextSecurePreferences.getLocalNumber(context));
TextSecureCipher cipher = new TextSecureCipher(localAddress, axolotlStore);
TextSecureMessage message = cipher.decrypt(envelope);
@@ -135,7 +144,7 @@ public class PushDecryptJob extends MasterSecretJob {
}
private void handleEndSessionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope,
TextSecureMessage message, long smsMessageId)
TextSecureMessage message, Optional<Long> smsMessageId)
{
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(envelope.getSource(),
@@ -145,13 +154,13 @@ public class PushDecryptJob extends MasterSecretJob {
long threadId;
if (smsMessageId <= 0) {
if (!smsMessageId.isPresent()) {
IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage);
Pair<Long, Long> messageAndThreadId = smsDatabase.insertMessageInbox(masterSecret, incomingEndSessionMessage);
threadId = messageAndThreadId.second;
} else {
smsDatabase.markAsEndSession(smsMessageId);
threadId = smsDatabase.getThreadIdForMessage(smsMessageId);
smsDatabase.markAsEndSession(smsMessageId.get());
threadId = smsDatabase.getThreadIdForMessage(smsMessageId.get());
}
SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret);
@@ -161,117 +170,100 @@ public class PushDecryptJob extends MasterSecretJob {
MessageNotifier.updateNotification(context, masterSecret, threadId);
}
private void handleGroupMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureMessage message, long smsMessageId) {
private void handleGroupMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureMessage message, Optional<Long> smsMessageId) {
GroupMessageProcessor.process(context, masterSecret, envelope, message);
if (smsMessageId > 0) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId);
if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
}
}
private void handleMediaMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureMessage message, long smsMessageId)
private void handleMediaMessage(MasterSecret masterSecret, TextSecureEnvelope envelope,
TextSecureMessage message, Optional<Long> smsMessageId)
throws MmsException
{
String localNumber = TextSecurePreferences.getLocalNumber(context);
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
localNumber, message.getTimestamp(),
Optional.fromNullable(envelope.getRelay()),
message.getBody(),
message.getGroupInfo(),
message.getAttachments());
Pair<Long, Long> messageAndThreadId;
if (message.isSecure()) {
messageAndThreadId = database.insertSecureDecryptedMessageInbox(masterSecret, mediaMessage, -1);
if (message.getSyncContext().isPresent()) {
messageAndThreadId = insertSyncMediaMessage(masterSecret, envelope, message);
} else {
messageAndThreadId = database.insertMessageInbox(masterSecret, mediaMessage, null, -1);
messageAndThreadId = insertStandardMediaMessage(masterSecret, envelope, message);
}
ApplicationContext.getInstance(context)
.getJobManager()
.add(new AttachmentDownloadJob(context, messageAndThreadId.first));
if (smsMessageId >= 0) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId);
if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
}
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
}
private void handleTextMessage(MasterSecret masterSecret, TextSecureEnvelope envelope,
TextSecureMessage message, long smsMessageId)
TextSecureMessage message, Optional<Long> smsMessageId)
{
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
String body = message.getBody().isPresent() ? message.getBody().get() : "";
Pair<Long, Long> messageAndThreadId;
if (smsMessageId > 0) {
database.updateBundleMessageBody(masterSecret, smsMessageId, body);
if (message.getSyncContext().isPresent()) {
messageAndThreadId = insertSyncTextMessage(masterSecret, envelope, message, smsMessageId);
} else {
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(),
envelope.getSourceDevice(),
message.getTimestamp(), body,
message.getGroupInfo());
if (message.isSecure()) {
textMessage = new IncomingEncryptedMessage(textMessage, body);
}
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, textMessage);
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
messageAndThreadId = insertStandardTextMessage(masterSecret, envelope, message, smsMessageId);
}
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
}
private void handleInvalidVersionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
private void handleInvalidVersionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
if (smsMessageId <= 0) {
if (!smsMessageId.isPresent()) {
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
smsDatabase.markAsInvalidVersionKeyExchange(messageAndThreadId.first);
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
} else {
smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId);
smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId.get());
}
}
private void handleCorruptMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
private void handleCorruptMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
if (smsMessageId <= 0) {
if (!smsMessageId.isPresent()) {
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
smsDatabase.markAsDecryptFailed(messageAndThreadId.first);
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
} else {
smsDatabase.markAsDecryptFailed(smsMessageId);
smsDatabase.markAsDecryptFailed(smsMessageId.get());
}
}
private void handleNoSessionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
private void handleNoSessionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
if (smsMessageId <= 0) {
if (!smsMessageId.isPresent()) {
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
smsDatabase.markAsNoSession(messageAndThreadId.first);
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
} else {
smsDatabase.markAsNoSession(smsMessageId);
smsDatabase.markAsNoSession(smsMessageId.get());
}
}
private void handleLegacyMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
private void handleLegacyMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
if (smsMessageId <= 0) {
if (!smsMessageId.isPresent()) {
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
smsDatabase.markAsLegacyVersion(messageAndThreadId.first);
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
} else {
smsDatabase.markAsLegacyVersion(smsMessageId);
smsDatabase.markAsLegacyVersion(smsMessageId.get());
}
}
private void handleDuplicateMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
private void handleDuplicateMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
// Let's start ignoring these now
// SmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
//
@@ -284,7 +276,7 @@ public class PushDecryptJob extends MasterSecretJob {
// }
}
private void handleUntrustedIdentityMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
private void handleUntrustedIdentityMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
try {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false);
@@ -296,16 +288,16 @@ public class PushDecryptJob extends MasterSecretJob {
envelope.getTimestamp(), encoded,
Optional.<TextSecureGroup>absent());
if (smsMessageId <= 0) {
if (!smsMessageId.isPresent()) {
IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded);
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, bundleMessage);
database.addMismatchedIdentity(messageAndThreadId.first, recipientId, identityKey);
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
} else {
database.updateMessageBody(masterSecret, smsMessageId, encoded);
database.markAsPreKeyBundle(smsMessageId);
database.addMismatchedIdentity(smsMessageId, recipientId, identityKey);
database.updateMessageBody(masterSecret, smsMessageId.get(), encoded);
database.markAsPreKeyBundle(smsMessageId.get());
database.addMismatchedIdentity(smsMessageId.get(), recipientId, identityKey);
}
} catch (InvalidMessageException | InvalidVersionException e) {
throw new AssertionError(e);
@@ -323,4 +315,98 @@ public class PushDecryptJob extends MasterSecretJob {
return database.insertMessageInbox(masterSecret, textMessage);
}
private Pair<Long, Long> insertSyncTextMessage(MasterSecret masterSecret,
TextSecureEnvelope envelope,
TextSecureMessage message,
Optional<Long> smsMessageId)
{
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
Recipients recipients = getSyncMessageDestination(message);
String body = message.getBody().or("");
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
long messageId = database.insertMessageOutbox(masterSecret, threadId, outgoingTextMessage, false, message.getSyncContext().get().getTimestamp());
database.markAsSent(messageId);
database.markAsPush(messageId);
database.markAsSecure(messageId);
if (smsMessageId.isPresent()) {
database.deleteMessage(smsMessageId.get());
}
return new Pair<>(messageId, threadId);
}
private Pair<Long, Long> insertStandardTextMessage(MasterSecret masterSecret,
TextSecureEnvelope envelope,
TextSecureMessage message,
Optional<Long> smsMessageId)
{
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
String body = message.getBody().isPresent() ? message.getBody().get() : "";
if (smsMessageId.isPresent()) {
return database.updateBundleMessageBody(masterSecret, smsMessageId.get(), body);
} else {
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(),
envelope.getSourceDevice(),
message.getTimestamp(), body,
message.getGroupInfo());
textMessage = new IncomingEncryptedMessage(textMessage, body);
return database.insertMessageInbox(masterSecret, textMessage);
}
}
private Pair<Long, Long> insertSyncMediaMessage(MasterSecret masterSecret,
TextSecureEnvelope envelope,
TextSecureMessage message)
throws MmsException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
TextSecureSyncContext syncContext = message.getSyncContext().get();
Recipients recipients = getSyncMessageDestination(message);
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(context, masterSecret, recipients,
message.getAttachments().get(),
message.getBody().orNull());
mediaMessage = new OutgoingSecureMediaMessage(mediaMessage);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
long messageId = database.insertMessageOutbox(masterSecret, mediaMessage, threadId, false, syncContext.getTimestamp());
database.markAsSent(messageId, "push".getBytes(), 0);
database.markAsPush(messageId);
return new Pair<>(messageId, threadId);
}
private Pair<Long, Long> insertStandardMediaMessage(MasterSecret masterSecret,
TextSecureEnvelope envelope,
TextSecureMessage message)
throws MmsException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
String localNumber = TextSecurePreferences.getLocalNumber(context);
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
localNumber, message.getTimestamp(),
Optional.fromNullable(envelope.getRelay()),
message.getBody(),
message.getGroupInfo(),
message.getAttachments());
return database.insertSecureDecryptedMessageInbox(masterSecret, mediaMessage, -1);
}
private Recipients getSyncMessageDestination(TextSecureMessage message) {
if (message.getGroupInfo().isPresent()) {
return RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId()), false);
} else {
return RecipientFactory.getRecipientsFromString(context, message.getSyncContext().get().getDestination(), false);
}
}
}

View File

@@ -3,9 +3,18 @@ package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.text.TextUtils;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.textsecure.api.messages.TextSecureAttachment;
import java.util.List;
import ws.com.google.android.mms.pdu.PduBody;
import ws.com.google.android.mms.pdu.PduPart;
public class OutgoingMediaMessage {
@@ -31,6 +40,14 @@ public class OutgoingMediaMessage {
this(context, recipients, slideDeck.toPduBody(), message, distributionType);
}
public OutgoingMediaMessage(Context context, MasterSecret masterSecret,
Recipients recipients, List<TextSecureAttachment> attachments,
String message)
{
this(context, recipients, pduBodyFor(masterSecret, attachments), message,
ThreadDatabase.DistributionTypes.CONVERSATION);
}
public OutgoingMediaMessage(OutgoingMediaMessage that) {
this.recipients = that.getRecipients();
this.body = that.body;
@@ -57,4 +74,24 @@ public class OutgoingMediaMessage {
return false;
}
private static PduBody pduBodyFor(MasterSecret masterSecret, List<TextSecureAttachment> attachments) {
PduBody body = new PduBody();
for (TextSecureAttachment attachment : attachments) {
if (attachment.isPointer()) {
PduPart media = new PduPart();
byte[] encryptedKey = new MasterCipher(masterSecret).encryptBytes(attachment.asPointer().getKey());
media.setContentType(Util.toIsoBytes(attachment.getContentType()));
media.setContentLocation(Util.toIsoBytes(String.valueOf(attachment.asPointer().getId())));
media.setContentDisposition(Util.toIsoBytes(Base64.encodeBytes(encryptedKey)));
media.setPendingPush(true);
body.addPart(media);
}
}
return body;
}
}

View File

@@ -73,7 +73,7 @@ public class MessageSender {
allocatedThreadId = threadId;
}
long messageId = database.insertMessageOutbox(masterSecret, allocatedThreadId, message, forceSms);
long messageId = database.insertMessageOutbox(masterSecret, allocatedThreadId, message, forceSms, System.currentTimeMillis());
sendTextMessage(context, recipients, forceSms, keyExchange, messageId);
@@ -99,7 +99,7 @@ public class MessageSender {
}
Recipients recipients = message.getRecipients();
long messageId = database.insertMessageOutbox(masterSecret, message, allocatedThreadId, forceSms);
long messageId = database.insertMessageOutbox(masterSecret, message, allocatedThreadId, forceSms, System.currentTimeMillis());
sendMediaMessage(context, masterSecret, recipients, forceSms, messageId);