clean up deprecated message connection

This commit is contained in:
Ryan ZHAO 2021-02-22 16:29:48 +11:00
parent 5b15decdd6
commit c5ab13aadf
17 changed files with 14 additions and 2061 deletions

View File

@ -49,7 +49,6 @@ import android.widget.Toast;
import androidx.annotation.DimenRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.annimon.stream.Stream;
@ -71,17 +70,12 @@ import org.thoughtcrime.securesms.components.StickerView;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.database.model.Quote;
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob;
import org.thoughtcrime.securesms.jobs.MmsDownloadJob;
import org.thoughtcrime.securesms.jobs.MmsSendJob;
import org.thoughtcrime.securesms.jobs.SmsSendJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
@ -1114,21 +1108,13 @@ public class ConversationItem extends LinearLayout
@Override
public void onClick(View v, final List<Slide> slides) {
Log.i(TAG, "onClick() for attachment download");
if (messageRecord.isMmsNotification()) {
Log.i(TAG, "Scheduling MMS attachment download");
ApplicationContext.getInstance(context)
.getJobManager()
.add(new MmsDownloadJob(messageRecord.getId(),
messageRecord.getThreadId(), false));
} else {
Log.i(TAG, "Scheduling push attachment downloads for " + slides.size() + " items");
Log.i(TAG, "Scheduling push attachment downloads for " + slides.size() + " items");
for (Slide slide : slides) {
ApplicationContext.getInstance(context)
.getJobManager()
.add(new AttachmentDownloadJob(messageRecord.getId(),
((DatabaseAttachment)slide.asAttachment()).getAttachmentId(), true));
}
for (Slide slide : slides) {
ApplicationContext.getInstance(context)
.getJobManager()
.add(new AttachmentDownloadJob(messageRecord.getId(),
((DatabaseAttachment)slide.asAttachment()).getAttachmentId(), true));
}
}
}
@ -1224,58 +1210,7 @@ public class ConversationItem extends LinearLayout
intent.putExtra(MessageDetailsActivity.IS_PUSH_GROUP_EXTRA, groupThread && messageRecord.isPush());
intent.putExtra(MessageDetailsActivity.ADDRESS_EXTRA, conversationRecipient.getAddress());
context.startActivity(intent);
} else if (!messageRecord.isOutgoing() && messageRecord.isIdentityMismatchFailure()) {
// handleApproveIdentity();
} else if (messageRecord.isPendingInsecureSmsFallback()) {
handleMessageApproval();
}
}
}
private void handleMessageApproval() {
final int title;
final int message;
if (messageRecord.isMms()) title = R.string.ConversationItem_click_to_approve_unencrypted_mms_dialog_title;
else title = R.string.ConversationItem_click_to_approve_unencrypted_sms_dialog_title;
message = R.string.ConversationItem_click_to_approve_unencrypted_dialog_message;
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title);
if (message > -1) builder.setMessage(message);
builder.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
if (messageRecord.isMms()) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
database.markAsInsecure(messageRecord.getId());
database.markAsOutbox(messageRecord.getId());
database.markAsForcedSms(messageRecord.getId());
ApplicationContext.getInstance(context)
.getJobManager()
.add(new MmsSendJob(messageRecord.getId()));
} else {
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
database.markAsInsecure(messageRecord.getId());
database.markAsOutbox(messageRecord.getId());
database.markAsForcedSms(messageRecord.getId());
ApplicationContext.getInstance(context)
.getJobManager()
.add(new SmsSendJob(context, messageRecord.getId(),
messageRecord.getIndividualRecipient().getAddress().serialize()));
}
});
builder.setNegativeButton(R.string.no, (dialogInterface, i) -> {
if (messageRecord.isMms()) {
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageRecord.getId());
} else {
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageRecord.getId());
}
});
builder.show();
}
}

View File

@ -244,7 +244,13 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
"ClosedGroupUpdateMessageSendJob",
"NullMessageSendJob",
"StickerDownloadJob",
"StickerPackDownloadJob");
"StickerPackDownloadJob",
"MmsSendJob",
"MmsReceiveJob",
"MmsDownloadJob",
"SmsSendJob",
"SmsSentJob",
"SmsReceiveJob");
}
db.setTransactionSuccessful();

View File

@ -37,9 +37,6 @@ public final class JobManagerFactories {
put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory());
put(ClosedGroupUpdateMessageSendJobV2.KEY, new ClosedGroupUpdateMessageSendJobV2.Factory());
put(LocalBackupJob.KEY, new LocalBackupJob.Factory());
put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory());
put(MmsReceiveJob.KEY, new MmsReceiveJob.Factory());
put(MmsSendJob.KEY, new MmsSendJob.Factory());
put(PushContentReceiveJob.KEY, new PushContentReceiveJob.Factory());
put(PushDecryptJob.KEY, new PushDecryptJob.Factory());
put(PushGroupSendJob.KEY, new PushGroupSendJob.Factory());
@ -50,9 +47,6 @@ public final class JobManagerFactories {
put(RetrieveProfileAvatarJob.KEY, new RetrieveProfileAvatarJob.Factory(application));
put(SendDeliveryReceiptJob.KEY, new SendDeliveryReceiptJob.Factory());
put(SendReadReceiptJob.KEY, new SendReadReceiptJob.Factory());
put(SmsReceiveJob.KEY, new SmsReceiveJob.Factory());
put(SmsSendJob.KEY, new SmsSendJob.Factory());
put(SmsSentJob.KEY, new SmsSentJob.Factory());
put(TrimThreadJob.KEY, new TrimThreadJob.Factory());
put(TypingSendJob.KEY, new TypingSendJob.Factory());
put(UpdateApkJob.KEY, new UpdateApkJob.Factory());

View File

@ -1,268 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.mms.pdu_alt.CharacterSets;
import com.google.android.mms.pdu_alt.EncodedStringValue;
import com.google.android.mms.pdu_alt.PduBody;
import com.google.android.mms.pdu_alt.PduPart;
import com.google.android.mms.pdu_alt.RetrieveConf;
import org.session.libsession.messaging.jobs.Data;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsRadioException;
import org.thoughtcrime.securesms.mms.PartParser;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.attachments.UriAttachment;
import org.session.libsession.messaging.threads.Address;
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class MmsDownloadJob extends BaseJob {
public static final String KEY = "MmsDownloadJob";
private static final String TAG = MmsDownloadJob.class.getSimpleName();
private static final String KEY_MESSAGE_ID = "message_id";
private static final String KEY_THREAD_ID = "thread_id";
private static final String KEY_AUTOMATIC = "automatic";
private long messageId;
private long threadId;
private boolean automatic;
private MessageNotifier messageNotifier;
public MmsDownloadJob(long messageId, long threadId, boolean automatic) {
this(new Job.Parameters.Builder()
.setQueue("mms-operation")
.setMaxAttempts(25)
.build(),
messageId,
threadId,
automatic);
}
private MmsDownloadJob(@NonNull Job.Parameters parameters, long messageId, long threadId, boolean automatic) {
super(parameters);
this.messageId = messageId;
this.threadId = threadId;
this.automatic = automatic;
this.messageNotifier = ApplicationContext.getInstance(context).messageNotifier;
}
@Override
public @NonNull
Data serialize() {
return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
.putLong(KEY_THREAD_ID, threadId)
.putBoolean(KEY_AUTOMATIC, automatic)
.build();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onAdded() {
if (automatic && KeyCachingService.isLocked(context)) {
DatabaseFactory.getMmsDatabase(context).markIncomingNotificationReceived(threadId);
messageNotifier.updateNotification(context);
}
}
@Override
public void onRun() {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Optional<MmsDatabase.MmsNotificationInfo> notification = database.getNotification(messageId);
if (!notification.isPresent()) {
Log.w(TAG, "No notification for ID: " + messageId);
return;
}
try {
if (notification.get().getContentLocation() == null) {
throw new MmsException("Notification content location was null.");
}
if (!TextSecurePreferences.isPushRegistered(context)) {
throw new MmsException("Not registered");
}
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
String contentLocation = notification.get().getContentLocation();
byte[] transactionId = new byte[0];
try {
if (notification.get().getTransactionId() != null) {
transactionId = notification.get().getTransactionId().getBytes(CharacterSets.MIMENAME_ISO_8859_1);
} else {
Log.w(TAG, "No transaction ID!");
}
} catch (UnsupportedEncodingException e) {
Log.w(TAG, e);
}
Log.i(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost() + ", subscription ID: " + notification.get().getSubscriptionId());
RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId, notification.get().getSubscriptionId());
if (retrieveConf == null) {
throw new MmsException("RetrieveConf was null");
}
storeRetrievedMms(contentLocation, messageId, threadId, retrieveConf, notification.get().getSubscriptionId(), notification.get().getFrom());
} catch (ApnUnavailableException e) {
Log.w(TAG, e);
handleDownloadError(messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE,
automatic);
} catch (MmsException e) {
Log.w(TAG, e);
handleDownloadError(messageId, threadId,
MmsDatabase.Status.DOWNLOAD_HARD_FAILURE,
automatic);
} catch (MmsRadioException | IOException e) {
Log.w(TAG, e);
handleDownloadError(messageId, threadId,
MmsDatabase.Status.DOWNLOAD_SOFT_FAILURE,
automatic);
}
}
@Override
public void onCanceled() {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_SOFT_FAILURE);
if (automatic) {
database.markIncomingNotificationReceived(threadId);
messageNotifier.updateNotification(context, threadId);
}
}
@Override
public boolean onShouldRetry(@NonNull Exception exception) {
return false;
}
private void storeRetrievedMms(String contentLocation,
long messageId, long threadId, RetrieveConf retrieved,
int subscriptionId, @Nullable Address notificationFrom)
throws MmsException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Optional<Address> group = Optional.absent();
Set<Address> members = new HashSet<>();
String body = null;
List<Attachment> attachments = new LinkedList<>();
Address from;
if (retrieved.getFrom() != null) {
from = Address.fromExternal(context, Util.toIsoString(retrieved.getFrom().getTextString()));
} else if (notificationFrom != null) {
from = notificationFrom;
} else {
from = Address.Companion.getUNKNOWN();
}
if (retrieved.getTo() != null) {
for (EncodedStringValue toValue : retrieved.getTo()) {
members.add(Address.fromExternal(context, Util.toIsoString(toValue.getTextString())));
}
}
if (retrieved.getCc() != null) {
for (EncodedStringValue ccValue : retrieved.getCc()) {
members.add(Address.fromExternal(context, Util.toIsoString(ccValue.getTextString())));
}
}
members.add(from);
members.add(Address.fromExternal(context, TextSecurePreferences.getLocalNumber(context)));
if (retrieved.getBody() != null) {
body = PartParser.getMessageText(retrieved.getBody());
PduBody media = PartParser.getSupportedMediaParts(retrieved.getBody());
for (int i=0;i<media.getPartsNum();i++) {
PduPart part = media.getPart(i);
if (part.getData() != null) {
Uri uri = BlobProvider.getInstance().forData(part.getData()).createForSingleUseInMemory();
String name = null;
if (part.getName() != null) name = Util.toIsoString(part.getName());
attachments.add(new UriAttachment(uri, Util.toIsoString(part.getContentType()),
AttachmentDatabase.TRANSFER_PROGRESS_DONE,
part.getData().length, name, false, false, null, null));
}
}
}
if (members.size() > 2) {
group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), new LinkedList<>())));
}
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false, false);
Optional<InsertResult> insertResult = database.insertMessageInbox(message, contentLocation, threadId);
if (insertResult.isPresent()) {
database.delete(messageId);
messageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
}
private void handleDownloadError(long messageId, long threadId, int downloadStatus, boolean automatic)
{
MmsDatabase db = DatabaseFactory.getMmsDatabase(context);
db.markDownloadState(messageId, downloadStatus);
if (automatic) {
db.markIncomingNotificationReceived(threadId);
messageNotifier.updateNotification(context, threadId);
}
}
public static final class Factory implements Job.Factory<MmsDownloadJob> {
@Override
public @NonNull MmsDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) {
return new MmsDownloadJob(parameters,
data.getLong(KEY_MESSAGE_ID),
data.getLong(KEY_THREAD_ID),
data.getBoolean(KEY_AUTOMATIC));
}
}
}

View File

@ -1,126 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import org.session.libsession.messaging.jobs.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.session.libsignal.utilities.logging.Log;
import androidx.annotation.NonNull;
import android.util.Pair;
import com.google.android.mms.pdu_alt.GenericPdu;
import com.google.android.mms.pdu_alt.NotificationInd;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.PduParser;
import org.thoughtcrime.securesms.ApplicationContext;
import org.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsignal.utilities.Base64;
import org.session.libsession.utilities.Util;
import java.io.IOException;
public class MmsReceiveJob extends BaseJob {
public static final String KEY = "MmsReceiveJob";
private static final String TAG = MmsReceiveJob.class.getSimpleName();
private static final String KEY_DATA = "data";
private static final String KEY_SUBSCRIPTION_ID = "subscription_id";
private byte[] data;
private int subscriptionId;
public MmsReceiveJob(byte[] data, int subscriptionId) {
this(new Job.Parameters.Builder().setMaxAttempts(25).build(), data, subscriptionId);
}
private MmsReceiveJob(@NonNull Job.Parameters parameters, byte[] data, int subscriptionId) {
super(parameters);
this.data = data;
this.subscriptionId = subscriptionId;
}
@Override
public @NonNull
Data serialize() {
return new Data.Builder().putString(KEY_DATA, Base64.encodeBytes(data))
.putInt(KEY_SUBSCRIPTION_ID, subscriptionId)
.build();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onRun() {
if (data == null) {
Log.w(TAG, "Received NULL pdu, ignoring...");
return;
}
PduParser parser = new PduParser(data);
GenericPdu pdu = null;
try {
pdu = parser.parse();
} catch (RuntimeException e) {
Log.w(TAG, e);
}
if (isNotification(pdu) && !isBlocked(pdu)) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox((NotificationInd)pdu, subscriptionId);
Log.i(TAG, "Inserted received MMS notification...");
ApplicationContext.getInstance(context)
.getJobManager()
.add(new MmsDownloadJob(messageAndThreadId.first,
messageAndThreadId.second,
true));
} else if (isNotification(pdu)) {
Log.w(TAG, "*** Received blocked MMS, ignoring...");
}
}
@Override
public void onCanceled() {
// TODO
}
@Override
public boolean onShouldRetry(@NonNull Exception exception) {
return false;
}
private boolean isBlocked(GenericPdu pdu) {
if (pdu.getFrom() != null && pdu.getFrom().getTextString() != null) {
Recipient recipients = Recipient.from(context, Address.fromExternal(context, Util.toIsoString(pdu.getFrom().getTextString())), false);
return recipients.isBlocked();
}
return false;
}
private boolean isNotification(GenericPdu pdu) {
return pdu != null && pdu.getMessageType() == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;
}
public static final class Factory implements Job.Factory<MmsReceiveJob> {
@Override
public @NonNull MmsReceiveJob create(@NonNull Parameters parameters, @NonNull Data data) {
try {
return new MmsReceiveJob(parameters, Base64.decode(data.getString(KEY_DATA)), data.getInt(KEY_SUBSCRIPTION_ID));
} catch (IOException e) {
throw new AssertionError(e);
}
}
}
}

View File

@ -1,326 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import androidx.annotation.NonNull;
import android.text.TextUtils;
import android.webkit.MimeTypeMap;
import com.android.mms.dom.smil.parser.SmilXmlSerializer;
import com.google.android.mms.ContentType;
import com.google.android.mms.InvalidHeaderValueException;
import com.google.android.mms.pdu_alt.CharacterSets;
import com.google.android.mms.pdu_alt.EncodedStringValue;
import com.google.android.mms.pdu_alt.PduBody;
import com.google.android.mms.pdu_alt.PduComposer;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.PduPart;
import com.google.android.mms.pdu_alt.SendConf;
import com.google.android.mms.pdu_alt.SendReq;
import com.google.android.mms.smil.SmilHelper;
import com.klinker.android.send_message.Utils;
import org.session.libsession.messaging.jobs.Data;
import org.thoughtcrime.securesms.ApplicationContext;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsSendResult;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.session.libsignal.utilities.Hex;
import org.session.libsession.utilities.NumberUtil;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class MmsSendJob extends SendJob {
public static final String KEY = "MmsSendJob";
private static final String TAG = MmsSendJob.class.getSimpleName();
private static final String KEY_MESSAGE_ID = "message_id";
private long messageId;
public MmsSendJob(long messageId) {
this(new Job.Parameters.Builder()
.setQueue("mms-operation")
.addConstraint(NetworkConstraint.KEY)
.setMaxAttempts(25)
.build(),
messageId);
}
private MmsSendJob(@NonNull Job.Parameters parameters, long messageId) {
super(parameters);
this.messageId = messageId;
}
@Override
public @NonNull
Data serialize() {
return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId).build();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onSend() throws MmsException, NoSuchMessageException, IOException {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
OutgoingMediaMessage message = database.getOutgoingMessage(messageId);
if (database.isSent(messageId)) {
Log.w(TAG, "Message " + messageId + " was already sent. Ignoring.");
return;
}
try {
Log.i(TAG, "Sending message: " + messageId);
SendReq pdu = constructSendPdu(message);
validateDestinations(message, pdu);
final byte[] pduBytes = getPduBytes(pdu);
final SendConf sendConf = new CompatMmsConnection(context).send(pduBytes, message.getSubscriptionId());
final MmsSendResult result = getSendResult(sendConf, pdu);
database.markAsSent(messageId, false);
markAttachmentsUploaded(messageId, message.getAttachments());
Log.i(TAG, "Sent message: " + messageId);
} catch (UndeliverableMessageException | IOException e) {
Log.w(TAG, e);
database.markAsSentFailed(messageId);
notifyMediaMessageDeliveryFailed(context, messageId);
} catch (InsecureFallbackApprovalException e) {
Log.w(TAG, e);
database.markAsPendingInsecureSmsFallback(messageId);
notifyMediaMessageDeliveryFailed(context, messageId);
}
}
@Override
public boolean onShouldRetry(@NonNull Exception exception) {
return false;
}
@Override
public void onCanceled() {
Log.i(TAG, "onCanceled() messageId: " + messageId);
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId);
notifyMediaMessageDeliveryFailed(context, messageId);
}
private byte[] getPduBytes(SendReq message)
throws IOException, UndeliverableMessageException, InsecureFallbackApprovalException
{
byte[] pduBytes = new PduComposer(context, message).make();
if (pduBytes == null) {
throw new UndeliverableMessageException("PDU composition failed, null payload");
}
return pduBytes;
}
private MmsSendResult getSendResult(SendConf conf, SendReq message)
throws UndeliverableMessageException
{
if (conf == null) {
throw new UndeliverableMessageException("No M-Send.conf received in response to send.");
} else if (conf.getResponseStatus() != PduHeaders.RESPONSE_STATUS_OK) {
throw new UndeliverableMessageException("Got bad response: " + conf.getResponseStatus());
} else if (isInconsistentResponse(message, conf)) {
throw new UndeliverableMessageException("Mismatched response!");
} else {
return new MmsSendResult(conf.getMessageId(), conf.getResponseStatus());
}
}
private boolean isInconsistentResponse(SendReq message, SendConf response) {
Log.i(TAG, "Comparing: " + Hex.toString(message.getTransactionId()));
Log.i(TAG, "With: " + Hex.toString(response.getTransactionId()));
return !Arrays.equals(message.getTransactionId(), response.getTransactionId());
}
private void validateDestinations(EncodedStringValue[] destinations) throws UndeliverableMessageException {
if (destinations == null) return;
for (EncodedStringValue destination : destinations) {
if (destination == null || !NumberUtil.isValidSmsOrEmail(destination.getString())) {
throw new UndeliverableMessageException("Invalid destination: " +
(destination == null ? null : destination.getString()));
}
}
}
private void validateDestinations(OutgoingMediaMessage media, SendReq message) throws UndeliverableMessageException {
validateDestinations(message.getTo());
validateDestinations(message.getCc());
validateDestinations(message.getBcc());
if (message.getTo() == null && message.getCc() == null && message.getBcc() == null) {
throw new UndeliverableMessageException("No to, cc, or bcc specified!");
}
if (media.isSecure()) {
throw new UndeliverableMessageException("Attempt to send encrypted MMS?");
}
}
private SendReq constructSendPdu(OutgoingMediaMessage message)
throws UndeliverableMessageException
{
SendReq req = new SendReq();
String lineNumber = getMyNumber(context);
Address destination = message.getRecipient().getAddress();
MediaConstraints mediaConstraints = MediaConstraints.getMmsMediaConstraints(message.getSubscriptionId());
List<Attachment> scaledAttachments = scaleAndStripExifFromAttachments(mediaConstraints, message.getAttachments());
if (!TextUtils.isEmpty(lineNumber)) {
req.setFrom(new EncodedStringValue(lineNumber));
} else {
req.setFrom(new EncodedStringValue(TextSecurePreferences.getLocalNumber(context)));
}
if (destination.isMmsGroup()) {
List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(destination.toGroupString(), false);
for (Recipient member : members) {
if (message.getDistributionType() == ThreadDatabase.DistributionTypes.BROADCAST) {
req.addBcc(new EncodedStringValue(member.getAddress().serialize()));
} else {
req.addTo(new EncodedStringValue(member.getAddress().serialize()));
}
}
} else {
req.addTo(new EncodedStringValue(destination.serialize()));
}
req.setDate(System.currentTimeMillis() / 1000);
PduBody body = new PduBody();
int size = 0;
if (!TextUtils.isEmpty(message.getBody())) {
PduPart part = new PduPart();
String name = String.valueOf(System.currentTimeMillis());
part.setData(Util.toUtf8Bytes(message.getBody()));
part.setCharset(CharacterSets.UTF_8);
part.setContentType(ContentType.TEXT_PLAIN.getBytes());
part.setContentId(name.getBytes());
part.setContentLocation((name + ".txt").getBytes());
part.setName((name + ".txt").getBytes());
body.addPart(part);
size += getPartSize(part);
}
for (Attachment attachment : scaledAttachments) {
try {
if (attachment.getDataUri() == null) throw new IOException("Assertion failed, attachment for outgoing MMS has no data!");
String fileName = attachment.getFileName();
PduPart part = new PduPart();
if (fileName == null) {
fileName = String.valueOf(Math.abs(Util.getSecureRandom().nextLong()));
String fileExtension = MimeTypeMap.getSingleton().getExtensionFromMimeType(attachment.getContentType());
if (fileExtension != null) fileName = fileName + "." + fileExtension;
}
if (attachment.getContentType().startsWith("text")) {
part.setCharset(CharacterSets.UTF_8);
}
part.setContentType(attachment.getContentType().getBytes());
part.setContentLocation(fileName.getBytes());
part.setName(fileName.getBytes());
int index = fileName.lastIndexOf(".");
String contentId = (index == -1) ? fileName : fileName.substring(0, index);
part.setContentId(contentId.getBytes());
part.setData(Util.readFully(PartAuthority.getAttachmentStream(context, attachment.getDataUri())));
body.addPart(part);
size += getPartSize(part);
} catch (IOException e) {
Log.w(TAG, e);
}
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
SmilXmlSerializer.serialize(SmilHelper.createSmilDocument(body), out);
PduPart smilPart = new PduPart();
smilPart.setContentId("smil".getBytes());
smilPart.setContentLocation("smil.xml".getBytes());
smilPart.setContentType(ContentType.APP_SMIL.getBytes());
smilPart.setData(out.toByteArray());
body.addPart(0, smilPart);
req.setBody(body);
req.setMessageSize(size);
req.setMessageClass(PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes());
req.setExpiry(7 * 24 * 60 * 60);
try {
req.setPriority(PduHeaders.PRIORITY_NORMAL);
req.setDeliveryReport(PduHeaders.VALUE_NO);
req.setReadReport(PduHeaders.VALUE_NO);
} catch (InvalidHeaderValueException e) {}
return req;
}
private long getPartSize(PduPart part) {
return part.getName().length + part.getContentLocation().length +
part.getContentType().length + part.getData().length +
part.getContentId().length;
}
private void notifyMediaMessageDeliveryFailed(Context context, long messageId) {
long threadId = DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId);
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
if (recipient != null) {
ApplicationContext.getInstance(context).messageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
}
}
private String getMyNumber(Context context) throws UndeliverableMessageException {
try {
return Utils.getMyPhoneNumber(context);
} catch (SecurityException e) {
throw new UndeliverableMessageException(e);
}
}
public static class Factory implements Job.Factory<MmsSendJob> {
@Override
public @NonNull MmsSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
return new MmsSendJob(parameters, data.getLong(KEY_MESSAGE_ID));
}
}
}

View File

@ -1,171 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.telephony.SmsMessage;
import org.session.libsession.messaging.jobs.Data;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.session.libsignal.utilities.Base64;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.libsignal.util.guava.Optional;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class SmsReceiveJob extends BaseJob {
public static final String KEY = "SmsReceiveJob";
private static final String TAG = SmsReceiveJob.class.getSimpleName();
private static final String KEY_PDUS = "pdus";
private static final String KEY_SUBSCRIPTION_ID = "subscription_id";
private @Nullable Object[] pdus;
private int subscriptionId;
public SmsReceiveJob(@Nullable Object[] pdus, int subscriptionId) {
this(new Job.Parameters.Builder()
.addConstraint(SqlCipherMigrationConstraint.KEY)
.setMaxAttempts(25)
.build(),
pdus,
subscriptionId);
}
private SmsReceiveJob(@NonNull Job.Parameters parameters, @Nullable Object[] pdus, int subscriptionId) {
super(parameters);
this.pdus = pdus;
this.subscriptionId = subscriptionId;
}
@Override
public @NonNull
Data serialize() {
String[] encoded = new String[pdus.length];
for (int i = 0; i < pdus.length; i++) {
encoded[i] = Base64.encodeBytes((byte[]) pdus[i]);
}
return new Data.Builder().putStringArray(KEY_PDUS, encoded)
.putInt(KEY_SUBSCRIPTION_ID, subscriptionId)
.build();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onRun() throws MigrationPendingException {
Log.i(TAG, "onRun()");
Optional<IncomingTextMessage> message = assembleMessageFragments(pdus, subscriptionId);
if (message.isPresent() && !isBlocked(message.get())) {
Optional<InsertResult> insertResult = storeMessage(message.get());
if (insertResult.isPresent()) {
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
} else if (message.isPresent()) {
Log.w(TAG, "*** Received blocked SMS, ignoring...");
} else {
Log.w(TAG, "*** Failed to assemble message fragments!");
}
}
@Override
public void onCanceled() {
}
@Override
public boolean onShouldRetry(@NonNull Exception exception) {
return exception instanceof MigrationPendingException;
}
private boolean isBlocked(IncomingTextMessage message) {
if (message.getSender() != null) {
Recipient recipient = Recipient.from(context, message.getSender(), false);
return recipient.isBlocked();
}
return false;
}
private Optional<InsertResult> storeMessage(IncomingTextMessage message) throws MigrationPendingException {
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
database.ensureMigration();
if (TextSecurePreferences.getNeedsSqlCipherMigration(context)) {
throw new MigrationPendingException();
}
if (message.isSecureMessage()) {
IncomingTextMessage placeholder = new IncomingTextMessage(message, "");
Optional<InsertResult> insertResult = database.insertMessageInbox(placeholder);
database.markAsLegacyVersion(insertResult.get().getMessageId());
return insertResult;
} else {
return database.insertMessageInbox(message);
}
}
private Optional<IncomingTextMessage> assembleMessageFragments(@Nullable Object[] pdus, int subscriptionId) {
if (pdus == null) {
return Optional.absent();
}
List<IncomingTextMessage> messages = new LinkedList<>();
for (Object pdu : pdus) {
messages.add(new IncomingTextMessage(context, SmsMessage.createFromPdu((byte[])pdu), subscriptionId));
}
if (messages.isEmpty()) {
return Optional.absent();
}
return Optional.of(new IncomingTextMessage(messages));
}
private class MigrationPendingException extends Exception {
}
public static final class Factory implements Job.Factory<SmsReceiveJob> {
@Override
public @NonNull SmsReceiveJob create(@NonNull Parameters parameters, @NonNull Data data) {
try {
int subscriptionId = data.getInt(KEY_SUBSCRIPTION_ID);
String[] encoded = data.getStringArray(KEY_PDUS);
Object[] pdus = new Object[encoded.length];
for (int i = 0; i < encoded.length; i++) {
pdus[i] = Base64.decode(encoded[i]);
}
return new SmsReceiveJob(parameters, pdus, subscriptionId);
} catch (IOException e) {
throw new AssertionError(e);
}
}
}
}

View File

@ -1,249 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import android.telephony.PhoneNumberUtils;
import android.telephony.SmsManager;
import org.session.libsession.messaging.jobs.Data;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraint;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsession.utilities.NumberUtil;
import org.session.libsession.utilities.TextSecurePreferences;
import java.util.ArrayList;
public class SmsSendJob extends SendJob {
public static final String KEY = "SmsSendJob";
private static final String TAG = SmsSendJob.class.getSimpleName();
private static final int MAX_ATTEMPTS = 25;
private static final String KEY_MESSAGE_ID = "message_id";
private static final String KEY_RUN_ATTEMPT = "run_attempt";
private long messageId;
private int runAttempt;
public SmsSendJob(Context context, long messageId, String name) {
this(context, messageId, name, 0);
}
public SmsSendJob(Context context, long messageId, String name, int runAttempt) {
this(constructParameters(context, name), messageId, runAttempt);
}
private SmsSendJob(@NonNull Job.Parameters parameters, long messageId, int runAttempt) {
super(parameters);
this.messageId = messageId;
this.runAttempt = runAttempt;
}
@Override
public @NonNull
Data serialize() {
return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
.putInt(KEY_RUN_ATTEMPT, runAttempt)
.build();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onSend() throws NoSuchMessageException, TooManyRetriesException {
if (runAttempt >= MAX_ATTEMPTS) {
warn(TAG, "Hit the retry limit. Failing.");
throw new TooManyRetriesException();
}
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
SmsMessageRecord record = database.getMessage(messageId);
if (!record.isPending() && !record.isFailed()) {
warn(TAG, "Message " + messageId + " was already sent. Ignoring.");
return;
}
try {
log(TAG, "Sending message: " + messageId + " (attempt " + runAttempt + ")");
deliver(record);
log(TAG, "Sent message: " + messageId);
} catch (UndeliverableMessageException ude) {
warn(TAG, ude);
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(record.getId());
ApplicationContext.getInstance(context).messageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
}
}
@Override
public boolean onShouldRetry(@NonNull Exception throwable) {
return false;
}
@Override
public void onCanceled() {
warn(TAG, "onCanceled() messageId: " + messageId);
long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
if (threadId != -1 && recipient != null) {
ApplicationContext.getInstance(context).messageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
}
}
private void deliver(SmsMessageRecord message)
throws UndeliverableMessageException
{
if (message.isSecure() || message.isKeyExchange() || message.isEndSession()) {
throw new UndeliverableMessageException("Trying to send a secure SMS?");
}
String recipient = message.getIndividualRecipient().getAddress().serialize();
// See issue #1516 for bug report, and discussion on commits related to #4833 for problems
// related to the original fix to #1516. This still may not be a correct fix if networks allow
// SMS/MMS sending to alphanumeric recipients other than email addresses, but should also
// help to fix issue #3099.
if (!NumberUtil.isValidEmail(recipient)) {
recipient = PhoneNumberUtils.stripSeparators(PhoneNumberUtils.convertKeypadLettersToDigits(recipient));
}
if (!NumberUtil.isValidSmsOrEmail(recipient)) {
throw new UndeliverableMessageException("Not a valid SMS destination! " + recipient);
}
ArrayList<String> messages = SmsManager.getDefault().divideMessage(message.getBody());
ArrayList<PendingIntent> sentIntents = constructSentIntents(message.getId(), message.getType(), messages, false);
ArrayList<PendingIntent> deliveredIntents = constructDeliveredIntents(message.getId(), message.getType(), messages);
// NOTE 11/04/14 -- There's apparently a bug where for some unknown recipients
// and messages, this will throw an NPE. We have no idea why, so we're just
// catching it and marking the message as a failure. That way at least it doesn't
// repeatedly crash every time you start the app.
try {
getSmsManagerFor(message.getSubscriptionId()).sendMultipartTextMessage(recipient, null, messages, sentIntents, deliveredIntents);
} catch (NullPointerException | IllegalArgumentException npe) {
warn(TAG, npe);
log(TAG, "Recipient: " + recipient);
log(TAG, "Message Parts: " + messages.size());
try {
for (int i=0;i<messages.size();i++) {
getSmsManagerFor(message.getSubscriptionId()).sendTextMessage(recipient, null, messages.get(i),
sentIntents.get(i),
deliveredIntents == null ? null : deliveredIntents.get(i));
}
} catch (NullPointerException | IllegalArgumentException npe2) {
warn(TAG, npe);
throw new UndeliverableMessageException(npe2);
}
} catch (SecurityException se) {
warn(TAG, se);
throw new UndeliverableMessageException(se);
}
}
private ArrayList<PendingIntent> constructSentIntents(long messageId, long type,
ArrayList<String> messages, boolean secure)
{
ArrayList<PendingIntent> sentIntents = new ArrayList<>(messages.size());
for (String ignored : messages) {
sentIntents.add(PendingIntent.getBroadcast(context, 0,
constructSentIntent(context, messageId, type, secure, false),
0));
}
return sentIntents;
}
private ArrayList<PendingIntent> constructDeliveredIntents(long messageId, long type, ArrayList<String> messages) {
if (!TextSecurePreferences.isSmsDeliveryReportsEnabled(context)) {
return null;
}
ArrayList<PendingIntent> deliveredIntents = new ArrayList<>(messages.size());
for (String ignored : messages) {
deliveredIntents.add(PendingIntent.getBroadcast(context, 0,
constructDeliveredIntent(context, messageId, type),
0));
}
return deliveredIntents;
}
private Intent constructSentIntent(Context context, long messageId, long type,
boolean upgraded, boolean push)
{
Intent pending = new Intent(SmsDeliveryListener.SENT_SMS_ACTION,
Uri.parse("custom://" + messageId + System.currentTimeMillis()),
context, SmsDeliveryListener.class);
pending.putExtra("type", type);
pending.putExtra("message_id", messageId);
pending.putExtra("run_attempt", Math.max(runAttempt, getRunAttempt()));
pending.putExtra("upgraded", upgraded);
pending.putExtra("push", push);
return pending;
}
private Intent constructDeliveredIntent(Context context, long messageId, long type) {
Intent pending = new Intent(SmsDeliveryListener.DELIVERED_SMS_ACTION,
Uri.parse("custom://" + messageId + System.currentTimeMillis()),
context, SmsDeliveryListener.class);
pending.putExtra("type", type);
pending.putExtra("message_id", messageId);
return pending;
}
private SmsManager getSmsManagerFor(int subscriptionId) {
if (Build.VERSION.SDK_INT >= 22 && subscriptionId != -1) {
return SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
} else {
return SmsManager.getDefault();
}
}
private static Job.Parameters constructParameters(@NonNull Context context, String name) {
String constraint = TextSecurePreferences.isWifiSmsEnabled(context) ? NetworkOrCellServiceConstraint.KEY
: CellServiceConstraint.KEY;
return new Job.Parameters.Builder()
.setMaxAttempts(MAX_ATTEMPTS)
.setQueue(name)
.addConstraint(constraint)
.build();
}
private static class TooManyRetriesException extends Exception { }
public static class Factory implements Job.Factory<SmsSendJob> {
@Override
public @NonNull SmsSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
return new SmsSendJob(parameters, data.getLong(KEY_MESSAGE_ID), data.getInt(KEY_RUN_ATTEMPT));
}
}
}

View File

@ -1,128 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.app.Activity;
import androidx.annotation.NonNull;
import android.telephony.SmsManager;
import org.session.libsession.messaging.jobs.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
public class SmsSentJob extends BaseJob {
public static final String KEY = "SmsSentJob";
private static final String TAG = SmsSentJob.class.getSimpleName();
private static final String KEY_MESSAGE_ID = "message_id";
private static final String KEY_ACTION = "action";
private static final String KEY_RESULT = "result";
private static final String KEY_RUN_ATTEMPT = "run_attempt";
private long messageId;
private String action;
private int result;
private int runAttempt;
public SmsSentJob(long messageId, String action, int result, int runAttempt) {
this(new Job.Parameters.Builder().build(),
messageId,
action,
result,
runAttempt);
}
private SmsSentJob(@NonNull Job.Parameters parameters, long messageId, String action, int result, int runAttempt) {
super(parameters);
this.messageId = messageId;
this.action = action;
this.result = result;
this.runAttempt = runAttempt;
}
@Override
public @NonNull
Data serialize() {
return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
.putString(KEY_ACTION, action)
.putInt(KEY_RESULT, result)
.putInt(KEY_RUN_ATTEMPT, runAttempt)
.build();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onRun() {
Log.i(TAG, "Got SMS callback: " + action + " , " + result);
switch (action) {
case SmsDeliveryListener.SENT_SMS_ACTION:
handleSentResult(messageId, result);
break;
case SmsDeliveryListener.DELIVERED_SMS_ACTION:
handleDeliveredResult(messageId, result);
break;
}
}
@Override
public boolean onShouldRetry(@NonNull Exception throwable) {
return false;
}
@Override
public void onCanceled() {
}
private void handleDeliveredResult(long messageId, int result) {
DatabaseFactory.getSmsDatabase(context).markStatus(messageId, result);
}
private void handleSentResult(long messageId, int result) {
try {
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
SmsMessageRecord record = database.getMessage(messageId);
switch (result) {
case Activity.RESULT_OK:
database.markAsSent(messageId, false);
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
case SmsManager.RESULT_ERROR_RADIO_OFF:
Log.w(TAG, "Service connectivity problem, requeuing...");
ApplicationContext.getInstance(context)
.getJobManager()
.add(new SmsSendJob(context, messageId, record.getIndividualRecipient().getAddress().serialize(), runAttempt + 1));
break;
default:
database.markAsSentFailed(messageId);
ApplicationContext.getInstance(context).messageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
}
} catch (NoSuchMessageException e) {
Log.w(TAG, e);
}
}
public static final class Factory implements Job.Factory<SmsSentJob> {
@Override
public @NonNull SmsSentJob create(@NonNull Parameters parameters, @NonNull Data data) {
return new SmsSentJob(parameters,
data.getLong(KEY_MESSAGE_ID),
data.getString(KEY_ACTION),
data.getInt(KEY_RESULT),
data.getInt(KEY_RUN_ATTEMPT));
}
}
}

View File

@ -1,100 +0,0 @@
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.session.libsignal.utilities.logging.Log;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.RetrieveConf;
import com.google.android.mms.pdu_alt.SendConf;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import java.io.IOException;
public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsConnection {
private static final String TAG = CompatMmsConnection.class.getSimpleName();
private Context context;
public CompatMmsConnection(Context context) {
this.context = context;
}
@Nullable
@Override
public SendConf send(@NonNull byte[] pduBytes, int subscriptionId)
throws UndeliverableMessageException
{
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP_MR1) {
try {
Log.i(TAG, "Sending via Lollipop API");
return new OutgoingLollipopMmsConnection(context).send(pduBytes, subscriptionId);
} catch (UndeliverableMessageException e) {
Log.w(TAG, e);
}
Log.i(TAG, "Falling back to legacy connection...");
}
if (subscriptionId == -1) {
Log.i(TAG, "Sending via legacy connection");
try {
SendConf result = new OutgoingLegacyMmsConnection(context).send(pduBytes, subscriptionId);
if (result != null && result.getResponseStatus() == PduHeaders.RESPONSE_STATUS_OK) {
return result;
} else {
Log.w(TAG, "Got bad legacy response: " + (result != null ? result.getResponseStatus() : null));
}
} catch (UndeliverableMessageException | ApnUnavailableException e) {
Log.w(TAG, e);
}
}
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && VERSION.SDK_INT < VERSION_CODES.LOLLIPOP_MR1) {
Log.i(TAG, "Falling back to sending via Lollipop API");
return new OutgoingLollipopMmsConnection(context).send(pduBytes, subscriptionId);
}
throw new UndeliverableMessageException("Both lollipop and legacy connections failed...");
}
@Nullable
@Override
public RetrieveConf retrieve(@NonNull String contentLocation,
byte[] transactionId,
int subscriptionId)
throws MmsException, MmsRadioException, ApnUnavailableException, IOException
{
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP_MR1) {
Log.i(TAG, "Receiving via Lollipop API");
try {
return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
} catch (MmsException e) {
Log.w(TAG, e);
}
Log.i(TAG, "Falling back to receiving via legacy connection");
}
if (VERSION.SDK_INT < 22 || subscriptionId == -1) {
Log.i(TAG, "Receiving via legacy API");
try {
return new IncomingLegacyMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
} catch (MmsRadioException | ApnUnavailableException | IOException e) {
Log.w(TAG, e);
}
}
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && VERSION.SDK_INT < VERSION_CODES.LOLLIPOP_MR1) {
Log.i(TAG, "Falling back to receiving via Lollipop API");
return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
}
throw new IOException("Both lollipop and fallback APIs failed...");
}
}

View File

@ -1,156 +0,0 @@
/**
* Copyright (C) 2015 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.session.libsignal.utilities.logging.Log;
import com.google.android.mms.InvalidHeaderValueException;
import com.google.android.mms.pdu_alt.NotifyRespInd;
import com.google.android.mms.pdu_alt.PduComposer;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.PduParser;
import com.google.android.mms.pdu_alt.RetrieveConf;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGetHC4;
import org.apache.http.client.methods.HttpUriRequest;
import java.io.IOException;
import java.util.Arrays;
@SuppressWarnings("deprecation")
public class IncomingLegacyMmsConnection extends LegacyMmsConnection implements IncomingMmsConnection {
private static final String TAG = IncomingLegacyMmsConnection.class.getSimpleName();
public IncomingLegacyMmsConnection(Context context) throws ApnUnavailableException {
super(context);
}
private HttpUriRequest constructRequest(Apn contentApn, boolean useProxy) throws IOException {
HttpGetHC4 request;
try {
request = new HttpGetHC4(contentApn.getMmsc());
} catch (IllegalArgumentException e) {
// #7339
throw new IOException(e);
}
for (Header header : getBaseHeaders()) {
request.addHeader(header);
}
if (useProxy) {
HttpHost proxy = new HttpHost(contentApn.getProxy(), contentApn.getPort());
request.setConfig(RequestConfig.custom().setProxy(proxy).build());
}
return request;
}
@Override
public @Nullable RetrieveConf retrieve(@NonNull String contentLocation,
byte[] transactionId, int subscriptionId)
throws MmsRadioException, ApnUnavailableException, IOException
{
MmsRadio radio = MmsRadio.getInstance(context);
Apn contentApn = new Apn(contentLocation, apn.getProxy(), Integer.toString(apn.getPort()), apn.getUsername(), apn.getPassword());
if (isDirectConnect()) {
Log.i(TAG, "Connecting directly...");
try {
return retrieve(contentApn, transactionId, false, false);
} catch (IOException | ApnUnavailableException e) {
Log.w(TAG, e);
}
}
Log.i(TAG, "Changing radio to MMS mode..");
radio.connect();
try {
Log.i(TAG, "Downloading in MMS mode with proxy...");
try {
return retrieve(contentApn, transactionId, true, true);
} catch (IOException | ApnUnavailableException e) {
Log.w(TAG, e);
}
Log.i(TAG, "Downloading in MMS mode without proxy...");
return retrieve(contentApn, transactionId, true, false);
} finally {
radio.disconnect();
}
}
public RetrieveConf retrieve(Apn contentApn, byte[] transactionId, boolean usingMmsRadio, boolean useProxyIfAvailable)
throws IOException, ApnUnavailableException
{
byte[] pdu = null;
final boolean useProxy = useProxyIfAvailable && contentApn.hasProxy();
final String targetHost = useProxy
? contentApn.getProxy()
: Uri.parse(contentApn.getMmsc()).getHost();
if (checkRouteToHost(context, targetHost, usingMmsRadio)) {
Log.i(TAG, "got successful route to host " + targetHost);
pdu = execute(constructRequest(contentApn, useProxy));
}
if (pdu == null) {
throw new IOException("Connection manager could not obtain route to host.");
}
RetrieveConf retrieved = (RetrieveConf)new PduParser(pdu).parse();
if (retrieved == null) {
Log.w(TAG, "Couldn't parse PDU, byte response: " + Arrays.toString(pdu));
Log.w(TAG, "Couldn't parse PDU, ASCII: " + new String(pdu));
throw new IOException("Bad retrieved PDU");
}
sendRetrievedAcknowledgement(transactionId, usingMmsRadio, useProxy);
return retrieved;
}
private void sendRetrievedAcknowledgement(byte[] transactionId,
boolean usingRadio,
boolean useProxy)
throws ApnUnavailableException
{
try {
NotifyRespInd notifyResponse = new NotifyRespInd(PduHeaders.CURRENT_MMS_VERSION,
transactionId,
PduHeaders.STATUS_RETRIEVED);
OutgoingLegacyMmsConnection connection = new OutgoingLegacyMmsConnection(context);
connection.sendNotificationReceived(new PduComposer(context, notifyResponse).make(), usingRadio, useProxy);
} catch (InvalidHeaderValueException | IOException e) {
Log.w(TAG, e);
}
}
}

View File

@ -1,162 +0,0 @@
/**
* Copyright (C) 2015 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.session.libsignal.utilities.logging.Log;
import com.google.android.mms.pdu_alt.PduParser;
import com.google.android.mms.pdu_alt.SendConf;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPostHC4;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ByteArrayEntityHC4;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import java.io.IOException;
@SuppressWarnings("deprecation")
public class OutgoingLegacyMmsConnection extends LegacyMmsConnection implements OutgoingMmsConnection {
private final static String TAG = OutgoingLegacyMmsConnection.class.getSimpleName();
public OutgoingLegacyMmsConnection(Context context) throws ApnUnavailableException {
super(context);
}
private HttpUriRequest constructRequest(byte[] pduBytes, boolean useProxy)
throws IOException
{
try {
HttpPostHC4 request = new HttpPostHC4(apn.getMmsc());
for (Header header : getBaseHeaders()) {
request.addHeader(header);
}
request.setEntity(new ByteArrayEntityHC4(pduBytes));
if (useProxy) {
HttpHost proxy = new HttpHost(apn.getProxy(), apn.getPort());
request.setConfig(RequestConfig.custom().setProxy(proxy).build());
}
return request;
} catch (IllegalArgumentException iae) {
throw new IOException(iae);
}
}
public void sendNotificationReceived(byte[] pduBytes, boolean usingMmsRadio, boolean useProxyIfAvailable)
throws IOException
{
sendBytes(pduBytes, usingMmsRadio, useProxyIfAvailable);
}
@Override
public @Nullable SendConf send(@NonNull byte[] pduBytes, int subscriptionId) throws UndeliverableMessageException {
try {
MmsRadio radio = MmsRadio.getInstance(context);
if (isDirectConnect()) {
Log.i(TAG, "Sending MMS directly without radio change...");
try {
return send(pduBytes, false, false);
} catch (IOException e) {
Log.w(TAG, e);
}
}
Log.i(TAG, "Sending MMS with radio change and proxy...");
radio.connect();
try {
try {
return send(pduBytes, true, true);
} catch (IOException e) {
Log.w(TAG, e);
}
Log.i(TAG, "Sending MMS with radio change and without proxy...");
try {
return send(pduBytes, true, false);
} catch (IOException ioe) {
Log.w(TAG, ioe);
throw new UndeliverableMessageException(ioe);
}
} finally {
radio.disconnect();
}
} catch (MmsRadioException e) {
Log.w(TAG, e);
throw new UndeliverableMessageException(e);
}
}
private SendConf send(byte[] pduBytes, boolean useMmsRadio, boolean useProxyIfAvailable) throws IOException {
byte[] response = sendBytes(pduBytes, useMmsRadio, useProxyIfAvailable);
return (SendConf) new PduParser(response).parse();
}
private byte[] sendBytes(byte[] pduBytes, boolean useMmsRadio, boolean useProxyIfAvailable) throws IOException {
final boolean useProxy = useProxyIfAvailable && apn.hasProxy();
final String targetHost = useProxy
? apn.getProxy()
: Uri.parse(apn.getMmsc()).getHost();
Log.i(TAG, "Sending MMS of length: " + pduBytes.length
+ (useMmsRadio ? ", using mms radio" : "")
+ (useProxy ? ", using proxy" : ""));
try {
if (checkRouteToHost(context, targetHost, useMmsRadio)) {
Log.i(TAG, "got successful route to host " + targetHost);
byte[] response = execute(constructRequest(pduBytes, useProxy));
if (response != null) return response;
}
} catch (IOException ioe) {
Log.w(TAG, ioe);
}
throw new IOException("Connection manager could not obtain route to host.");
}
public static boolean isConnectionPossible(Context context) {
try {
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(MmsRadio.TYPE_MOBILE_MMS);
if (networkInfo == null) {
Log.w(TAG, "MMS network info was null, unsupported by this device");
return false;
}
getApn(context);
return true;
} catch (ApnUnavailableException e) {
Log.w(TAG, e);
return false;
}
}
}

View File

@ -1,67 +0,0 @@
/**
* Copyright (C) 2011 Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.provider.Telephony;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobs.MmsReceiveJob;
import org.session.libsession.utilities.Util;
public class MmsListener extends BroadcastReceiver {
private static final String TAG = MmsListener.class.getSimpleName();
private boolean isRelevant(Context context, Intent intent) {
if (!ApplicationMigrationService.isDatabaseImported(context)) {
return false;
}
if (Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION.equals(intent.getAction()) && Util.isDefaultSmsProvider(context)) {
return false;
}
return false;
}
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Got MMS broadcast..." + intent.getAction());
if ((Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION.equals(intent.getAction()) &&
Util.isDefaultSmsProvider(context)) ||
(Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION.equals(intent.getAction()) &&
isRelevant(context, intent)))
{
Log.i(TAG, "Relevant!");
int subscriptionId = intent.getExtras().getInt("subscription", -1);
ApplicationContext.getInstance(context)
.getJobManager()
.add(new MmsReceiveJob(intent.getByteArrayExtra("data"), subscriptionId));
abortBroadcast();
}
}
}

View File

@ -1,69 +0,0 @@
package org.thoughtcrime.securesms.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.jobs.SmsSentJob;
public class SmsDeliveryListener extends BroadcastReceiver {
private static final String TAG = SmsDeliveryListener.class.getSimpleName();
public static final String SENT_SMS_ACTION = "org.thoughtcrime.securesms.SendReceiveService.SENT_SMS_ACTION";
public static final String DELIVERED_SMS_ACTION = "org.thoughtcrime.securesms.SendReceiveService.DELIVERED_SMS_ACTION";
@Override
public void onReceive(Context context, Intent intent) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
long messageId = intent.getLongExtra("message_id", -1);
int runAttempt = intent.getIntExtra("run_attempt", 0);
switch (intent.getAction()) {
case SENT_SMS_ACTION:
int result = getResultCode();
jobManager.add(new SmsSentJob(messageId, SENT_SMS_ACTION, result, runAttempt));
break;
case DELIVERED_SMS_ACTION:
byte[] pdu = intent.getByteArrayExtra("pdu");
if (pdu == null) {
Log.w(TAG, "No PDU in delivery receipt!");
break;
}
SmsMessage message = SmsMessage.createFromPdu(pdu);
if (message == null) {
Log.w(TAG, "Delivery receipt failed to parse!");
break;
}
int status = message.getStatus();
Log.i(TAG, "Original status: " + status);
// Note: https://developer.android.com/reference/android/telephony/SmsMessage.html#getStatus()
// " CDMA: For not interfering with status codes from GSM, the value is shifted to the bits 31-16"
// Note: https://stackoverflow.com/a/33240109
if ("3gpp2".equals(intent.getStringExtra("format"))) {
Log.w(TAG, "Correcting for CDMA delivery receipt...");
if (status >> 24 <= 0) status = SmsDatabase.Status.STATUS_COMPLETE;
else if (status >> 24 == 2) status = SmsDatabase.Status.STATUS_PENDING;
else if (status >> 24 == 3) status = SmsDatabase.Status.STATUS_FAILED;
}
jobManager.add(new SmsSentJob(messageId, DELIVERED_SMS_ACTION, status, runAttempt));
break;
default:
Log.w(TAG, "Unknown action: " + intent.getAction());
}
}
}

View File

@ -1,113 +0,0 @@
/**
* Copyright (C) 2011 Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Telephony;
import android.telephony.SmsMessage;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobs.SmsReceiveJob;
import org.session.libsession.utilities.Util;
public class SmsListener extends BroadcastReceiver {
private static final String SMS_RECEIVED_ACTION = Telephony.Sms.Intents.SMS_RECEIVED_ACTION;
private static final String SMS_DELIVERED_ACTION = Telephony.Sms.Intents.SMS_DELIVER_ACTION;
private boolean isExemption(SmsMessage message, String messageBody) {
// ignore CLASS0 ("flash") messages
if (message.getMessageClass() == SmsMessage.MessageClass.CLASS_0)
return true;
// ignore OTP messages from Sparebank1 (Norwegian bank)
if (messageBody.startsWith("Sparebank1://otp?")) {
return true;
}
return
message.getOriginatingAddress().length() < 7 &&
(messageBody.toUpperCase().startsWith("//ANDROID:") || // Sprint Visual Voicemail
messageBody.startsWith("//BREW:")); //BREW stands for Binary Runtime Environment for Wireless"
}
private SmsMessage getSmsMessageFromIntent(Intent intent) {
Bundle bundle = intent.getExtras();
Object[] pdus = (Object[])bundle.get("pdus");
if (pdus == null || pdus.length == 0)
return null;
return SmsMessage.createFromPdu((byte[])pdus[0]);
}
private String getSmsMessageBodyFromIntent(Intent intent) {
Bundle bundle = intent.getExtras();
Object[] pdus = (Object[])bundle.get("pdus");
StringBuilder bodyBuilder = new StringBuilder();
if (pdus == null)
return null;
for (Object pdu : pdus)
bodyBuilder.append(SmsMessage.createFromPdu((byte[])pdu).getDisplayMessageBody());
return bodyBuilder.toString();
}
private boolean isRelevant(Context context, Intent intent) {
SmsMessage message = getSmsMessageFromIntent(intent);
String messageBody = getSmsMessageBodyFromIntent(intent);
if (message == null && messageBody == null)
return false;
if (isExemption(message, messageBody))
return false;
if (!ApplicationMigrationService.isDatabaseImported(context))
return false;
if (SMS_RECEIVED_ACTION.equals(intent.getAction()) && Util.isDefaultSmsProvider(context)) {
return false;
}
return false;
}
@Override
public void onReceive(Context context, Intent intent) {
Log.i("SMSListener", "Got SMS broadcast...");
if ((intent.getAction().equals(SMS_DELIVERED_ACTION)) ||
(intent.getAction().equals(SMS_RECEIVED_ACTION)) && isRelevant(context, intent))
{
Log.i("SmsListener", "Constructing SmsReceiveJob...");
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
int subscriptionId = intent.getExtras().getInt("subscription", -1);
ApplicationContext.getInstance(context).getJobManager().add(new SmsReceiveJob(pdus, subscriptionId));
abortBroadcast();
}
}
}

View File

@ -33,11 +33,9 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobs.MmsSendJob;
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
import org.thoughtcrime.securesms.jobs.PushMediaSendJob;
import org.thoughtcrime.securesms.jobs.PushTextSendJob;
import org.thoughtcrime.securesms.jobs.SmsSendJob;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@ -142,13 +140,11 @@ public class MessageSender {
private static void sendTextPush(Context context, Recipient recipient, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
jobManager.add(new PushTextSendJob(messageId, recipient.getAddress()));
// MultiDeviceProtocol.sendTextPush(context, recipient, messageId);
}
private static void sendMediaPush(Context context, Recipient recipient, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
PushMediaSendJob.enqueue(context, jobManager, messageId, recipient.getAddress());
// MultiDeviceProtocol.sendMediaPush(context, recipient, messageId);
}
private static void sendGroupPush(Context context, Recipient recipient, long messageId, Address filterAddress) {
@ -156,48 +152,6 @@ public class MessageSender {
PushGroupSendJob.enqueue(context, jobManager, messageId, recipient.getAddress(), filterAddress);
}
private static void sendSms(Context context, Recipient recipient, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
jobManager.add(new SmsSendJob(context, messageId, recipient.getName()));
}
private static void sendMms(Context context, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
jobManager.add(new MmsSendJob(messageId));
}
private static boolean isPushTextSend(Context context, Recipient recipient, boolean keyExchange) {
return true;
// Loki - Original code
// ========
// if (!TextSecurePreferences.isPushRegistered(context)) {
// return false;
// }
//
// if (keyExchange) {
// return false;
// }
//
// return isPushDestination(context, recipient);
// ========
}
private static boolean isPushMediaSend(Context context, Recipient recipient) {
return true;
// Loki - Original code
// ========
// if (!TextSecurePreferences.isPushRegistered(context)) {
// return false;
// }
//
// if (recipient.isGroupRecipient()) {
// return false;
// }
//
// return isPushDestination(context, recipient);
// ========
}
private static boolean isGroupPushSend(Recipient recipient) {
return recipient.getAddress().isGroup() &&
!recipient.getAddress().isMmsGroup();

View File

@ -25,7 +25,6 @@ import android.os.Build.VERSION_CODES;
import android.text.TextUtils;
import org.thoughtcrime.securesms.components.ComposeText;
import org.thoughtcrime.securesms.mms.OutgoingLegacyMmsConnection;
import network.loki.messenger.BuildConfig;
@ -70,6 +69,6 @@ public class Util {
@TargetApi(VERSION_CODES.LOLLIPOP)
public static boolean isMmsCapable(Context context) {
return (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) || OutgoingLegacyMmsConnection.isConnectionPossible(context);
return VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP;
}
}