diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c4e916fcc..cdd0709c2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -400,27 +400,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/org/thoughtcrime/securesms/backup/FullBackupBase.java b/src/org/thoughtcrime/securesms/backup/FullBackupBase.java
deleted file mode 100644
index 431f60bd9..000000000
--- a/src/org/thoughtcrime/securesms/backup/FullBackupBase.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.thoughtcrime.securesms.backup;
-
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import org.greenrobot.eventbus.EventBus;
-import org.whispersystems.libsignal.util.ByteUtil;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-public abstract class FullBackupBase {
-
- @SuppressWarnings("unused")
- private static final String TAG = FullBackupBase.class.getSimpleName();
-
- static class BackupStream {
- static @NonNull byte[] getBackupKey(@NonNull String passphrase, @Nullable byte[] salt) {
- try {
- EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, 0));
-
- MessageDigest digest = MessageDigest.getInstance("SHA-512");
- byte[] input = passphrase.replace(" ", "").getBytes();
- byte[] hash = input;
-
- if (salt != null) digest.update(salt);
-
- for (int i=0;i<250000;i++) {
- if (i % 1000 == 0) EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, 0));
- digest.update(hash);
- hash = digest.digest(input);
- }
-
- return ByteUtil.trim(hash, 32);
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- }
- }
- }
-
- public static class BackupEvent {
- public enum Type {
- PROGRESS,
- FINISHED
- }
-
- private final Type type;
- private final int count;
-
- BackupEvent(Type type, int count) {
- this.type = type;
- this.count = count;
- }
-
- public Type getType() {
- return type;
- }
-
- public int getCount() {
- return count;
- }
- }
-
-}
diff --git a/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java b/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java
deleted file mode 100644
index ba165b269..000000000
--- a/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java
+++ /dev/null
@@ -1,384 +0,0 @@
-package org.thoughtcrime.securesms.backup;
-
-
-import android.content.Context;
-import android.database.Cursor;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.annimon.stream.function.Consumer;
-import com.annimon.stream.function.Predicate;
-import com.google.protobuf.ByteString;
-
-import net.sqlcipher.database.SQLiteDatabase;
-
-import org.greenrobot.eventbus.EventBus;
-import org.thoughtcrime.securesms.attachments.AttachmentId;
-import org.thoughtcrime.securesms.crypto.AttachmentSecret;
-import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
-import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
-import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
-import org.thoughtcrime.securesms.database.AttachmentDatabase;
-import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
-import org.thoughtcrime.securesms.database.MmsDatabase;
-import org.thoughtcrime.securesms.database.MmsSmsColumns;
-import org.thoughtcrime.securesms.database.OneTimePreKeyDatabase;
-import org.thoughtcrime.securesms.database.SearchDatabase;
-import org.thoughtcrime.securesms.database.SessionDatabase;
-import org.thoughtcrime.securesms.database.SignedPreKeyDatabase;
-import org.thoughtcrime.securesms.database.SmsDatabase;
-import org.thoughtcrime.securesms.profiles.AvatarHelper;
-import org.thoughtcrime.securesms.util.Conversions;
-import org.thoughtcrime.securesms.util.Util;
-import org.whispersystems.libsignal.kdf.HKDFv3;
-import org.whispersystems.libsignal.util.ByteUtil;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.Mac;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-public class FullBackupExporter extends FullBackupBase {
-
- @SuppressWarnings("unused")
- private static final String TAG = FullBackupExporter.class.getSimpleName();
-
- public static void export(@NonNull Context context,
- @NonNull AttachmentSecret attachmentSecret,
- @NonNull SQLiteDatabase input,
- @NonNull File output,
- @NonNull String passphrase)
- throws IOException
- {
- BackupFrameOutputStream outputStream = new BackupFrameOutputStream(output, passphrase);
- outputStream.writeDatabaseVersion(input.getVersion());
-
- List tables = exportSchema(input, outputStream);
- int count = 0;
-
- for (String table : tables) {
- if (table.equals(SmsDatabase.TABLE_NAME) || table.equals(MmsDatabase.TABLE_NAME)) {
- count = exportTable(table, input, outputStream, cursor -> cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.EXPIRES_IN)) <= 0, null, count);
- } else if (table.equals(GroupReceiptDatabase.TABLE_NAME)) {
- count = exportTable(table, input, outputStream, cursor -> isForNonExpiringMessage(input, cursor.getLong(cursor.getColumnIndexOrThrow(GroupReceiptDatabase.MMS_ID))), null, count);
- } else if (table.equals(AttachmentDatabase.TABLE_NAME)) {
- count = exportTable(table, input, outputStream, cursor -> isForNonExpiringMessage(input, cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.MMS_ID))), cursor -> exportAttachment(attachmentSecret, cursor, outputStream), count);
- } else if (!table.equals(SignedPreKeyDatabase.TABLE_NAME) &&
- !table.equals(OneTimePreKeyDatabase.TABLE_NAME) &&
- !table.equals(SessionDatabase.TABLE_NAME) &&
- !table.startsWith(SearchDatabase.SMS_FTS_TABLE_NAME) &&
- !table.startsWith(SearchDatabase.MMS_FTS_TABLE_NAME))
- {
- count = exportTable(table, input, outputStream, null, null, count);
- }
- }
-
- for (BackupProtos.SharedPreference preference : IdentityKeyUtil.getBackupRecord(context)) {
- EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, ++count));
- outputStream.write(preference);
- }
-
- for (File avatar : AvatarHelper.getAvatarFiles(context)) {
- EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, ++count));
- outputStream.write(avatar.getName(), new FileInputStream(avatar), avatar.length());
- }
-
- outputStream.writeEnd();
- outputStream.close();
- EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.FINISHED, ++count));
- }
-
- private static List exportSchema(@NonNull SQLiteDatabase input, @NonNull BackupFrameOutputStream outputStream)
- throws IOException
- {
- List tables = new LinkedList<>();
-
- try (Cursor cursor = input.rawQuery("SELECT sql, name, type FROM sqlite_master", null)) {
- while (cursor != null && cursor.moveToNext()) {
- String sql = cursor.getString(0);
- String name = cursor.getString(1);
- String type = cursor.getString(2);
-
- if (sql != null) {
-
- boolean isSmsFtsSecretTable = name != null && !name.equals(SearchDatabase.SMS_FTS_TABLE_NAME) && name.startsWith(SearchDatabase.SMS_FTS_TABLE_NAME);
- boolean isMmsFtsSecretTable = name != null && !name.equals(SearchDatabase.MMS_FTS_TABLE_NAME) && name.startsWith(SearchDatabase.MMS_FTS_TABLE_NAME);
-
- if (!isSmsFtsSecretTable && !isMmsFtsSecretTable) {
- if ("table".equals(type)) {
- tables.add(name);
- }
-
- outputStream.write(BackupProtos.SqlStatement.newBuilder().setStatement(cursor.getString(0)).build());
- }
- }
- }
- }
-
- return tables;
- }
-
- private static int exportTable(@NonNull String table,
- @NonNull SQLiteDatabase input,
- @NonNull BackupFrameOutputStream outputStream,
- @Nullable Predicate predicate,
- @Nullable Consumer postProcess,
- int count)
- throws IOException
- {
- String template = "INSERT INTO " + table + " VALUES ";
-
- try (Cursor cursor = input.rawQuery("SELECT * FROM " + table, null)) {
- while (cursor != null && cursor.moveToNext()) {
- EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, ++count));
-
- if (predicate == null || predicate.test(cursor)) {
- StringBuilder statement = new StringBuilder(template);
- BackupProtos.SqlStatement.Builder statementBuilder = BackupProtos.SqlStatement.newBuilder();
-
- statement.append('(');
-
- for (int i=0;i 0) {
- InputStream inputStream;
-
- if (random != null && random.length == 32) inputStream = ModernDecryptingPartInputStream.createFor(attachmentSecret, random, new File(data), 0);
- else inputStream = ClassicDecryptingPartInputStream.createFor(attachmentSecret, new File(data));
-
- outputStream.write(new AttachmentId(rowId, uniqueId), inputStream, size);
- }
- } catch (IOException e) {
- Log.w(TAG, e);
- }
- }
-
- private static long calculateVeryOldStreamLength(@NonNull AttachmentSecret attachmentSecret, @Nullable byte[] random, @NonNull String data) throws IOException {
- long result = 0;
- InputStream inputStream;
-
- if (random != null && random.length == 32) inputStream = ModernDecryptingPartInputStream.createFor(attachmentSecret, random, new File(data), 0);
- else inputStream = ClassicDecryptingPartInputStream.createFor(attachmentSecret, new File(data));
-
- int read;
- byte[] buffer = new byte[8192];
-
- while ((read = inputStream.read(buffer, 0, buffer.length)) != -1) {
- result += read;
- }
-
- return result;
- }
-
- private static boolean isForNonExpiringMessage(@NonNull SQLiteDatabase db, long mmsId) {
- String[] columns = new String[] { MmsDatabase.EXPIRES_IN };
- String where = MmsDatabase.ID + " = ?";
- String[] args = new String[] { String.valueOf(mmsId) };
-
- try (Cursor mmsCursor = db.query(MmsDatabase.TABLE_NAME, columns, where, args, null, null, null)) {
- if (mmsCursor != null && mmsCursor.moveToFirst()) {
- return mmsCursor.getLong(0) == 0;
- }
- }
-
- return false;
- }
-
-
- private static class BackupFrameOutputStream extends BackupStream {
-
- private final OutputStream outputStream;
- private final Cipher cipher;
- private final Mac mac;
-
- private final byte[] cipherKey;
- private final byte[] macKey;
-
- private byte[] iv;
- private int counter;
-
- private BackupFrameOutputStream(@NonNull File output, @NonNull String passphrase) throws IOException {
- try {
- byte[] salt = Util.getSecretBytes(32);
- byte[] key = getBackupKey(passphrase, salt);
- byte[] derived = new HKDFv3().deriveSecrets(key, "Backup Export".getBytes(), 64);
- byte[][] split = ByteUtil.split(derived, 32, 32);
-
- this.cipherKey = split[0];
- this.macKey = split[1];
-
- this.cipher = Cipher.getInstance("AES/CTR/NoPadding");
- this.mac = Mac.getInstance("HmacSHA256");
- this.outputStream = new FileOutputStream(output);
- this.iv = Util.getSecretBytes(16);
- this.counter = Conversions.byteArrayToInt(iv);
-
- mac.init(new SecretKeySpec(macKey, "HmacSHA256"));
-
- byte[] header = BackupProtos.BackupFrame.newBuilder().setHeader(BackupProtos.Header.newBuilder()
- .setIv(ByteString.copyFrom(iv))
- .setSalt(ByteString.copyFrom(salt)))
- .build().toByteArray();
-
- outputStream.write(Conversions.intToByteArray(header.length));
- outputStream.write(header);
- } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
- throw new AssertionError(e);
- }
- }
-
- public void write(BackupProtos.SharedPreference preference) throws IOException {
- write(outputStream, BackupProtos.BackupFrame.newBuilder().setPreference(preference).build());
- }
-
- public void write(BackupProtos.SqlStatement statement) throws IOException {
- write(outputStream, BackupProtos.BackupFrame.newBuilder().setStatement(statement).build());
- }
-
- public void write(@NonNull String avatarName, @NonNull InputStream in, long size) throws IOException {
- write(outputStream, BackupProtos.BackupFrame.newBuilder()
- .setAvatar(BackupProtos.Avatar.newBuilder()
- .setName(avatarName)
- .setLength(Util.toIntExact(size))
- .build())
- .build());
-
- writeStream(in);
- }
-
- public void write(@NonNull AttachmentId attachmentId, @NonNull InputStream in, long size) throws IOException {
- write(outputStream, BackupProtos.BackupFrame.newBuilder()
- .setAttachment(BackupProtos.Attachment.newBuilder()
- .setRowId(attachmentId.getRowId())
- .setAttachmentId(attachmentId.getUniqueId())
- .setLength(Util.toIntExact(size))
- .build())
- .build());
-
- writeStream(in);
- }
-
- void writeDatabaseVersion(int version) throws IOException {
- write(outputStream, BackupProtos.BackupFrame.newBuilder()
- .setVersion(BackupProtos.DatabaseVersion.newBuilder().setVersion(version))
- .build());
- }
-
- void writeEnd() throws IOException {
- write(outputStream, BackupProtos.BackupFrame.newBuilder().setEnd(true).build());
- }
-
- private void writeStream(@NonNull InputStream inputStream) throws IOException {
- try {
- Conversions.intToByteArray(iv, 0, counter++);
- cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), new IvParameterSpec(iv));
- mac.update(iv);
-
- byte[] buffer = new byte[8192];
- int read;
-
- while ((read = inputStream.read(buffer)) != -1) {
- byte[] ciphertext = cipher.update(buffer, 0, read);
-
- if (ciphertext != null) {
- outputStream.write(ciphertext);
- mac.update(ciphertext);
- }
- }
-
- byte[] remainder = cipher.doFinal();
- outputStream.write(remainder);
- mac.update(remainder);
-
- byte[] attachmentDigest = mac.doFinal();
- outputStream.write(attachmentDigest, 0, 10);
- } catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
- throw new AssertionError(e);
- }
- }
-
- private void write(@NonNull OutputStream out, @NonNull BackupProtos.BackupFrame frame) throws IOException {
- try {
- Conversions.intToByteArray(iv, 0, counter++);
- cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), new IvParameterSpec(iv));
-
- byte[] frameCiphertext = cipher.doFinal(frame.toByteArray());
- byte[] frameMac = mac.doFinal(frameCiphertext);
- byte[] length = Conversions.intToByteArray(frameCiphertext.length + 10);
-
- out.write(length);
- out.write(frameCiphertext);
- out.write(frameMac, 0, 10);
- } catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
- throw new AssertionError(e);
- }
- }
-
-
- public void close() throws IOException {
- outputStream.close();
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/database/ApnDatabase.java b/src/org/thoughtcrime/securesms/database/ApnDatabase.java
deleted file mode 100644
index ad069ea6b..000000000
--- a/src/org/thoughtcrime/securesms/database/ApnDatabase.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/**
- * Copyright (C) 2014 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 .
- */
-package org.thoughtcrime.securesms.database;
-
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import android.text.TextUtils;
-import android.util.Log;
-
-import org.thoughtcrime.securesms.mms.LegacyMmsConnection.Apn;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
-import org.whispersystems.libsignal.util.guava.Optional;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Database to query APN and MMSC information
- */
-public class ApnDatabase {
- private static final String TAG = ApnDatabase.class.getSimpleName();
-
- private final SQLiteDatabase db;
- private final Context context;
-
- private static final String DATABASE_NAME = "apns.db";
- private static final String ASSET_PATH = "databases" + File.separator + DATABASE_NAME;
-
- private static final String TABLE_NAME = "apns";
- private static final String ID_COLUMN = "_id";
- private static final String MCC_MNC_COLUMN = "mccmnc";
- private static final String MCC_COLUMN = "mcc";
- private static final String MNC_COLUMN = "mnc";
- private static final String CARRIER_COLUMN = "carrier";
- private static final String APN_COLUMN = "apn";
- private static final String MMSC_COLUMN = "mmsc";
- private static final String PORT_COLUMN = "port";
- private static final String TYPE_COLUMN = "type";
- private static final String PROTOCOL_COLUMN = "protocol";
- private static final String BEARER_COLUMN = "bearer";
- private static final String ROAMING_PROTOCOL_COLUMN = "roaming_protocol";
- private static final String CARRIER_ENABLED_COLUMN = "carrier_enabled";
- private static final String MMS_PROXY_COLUMN = "mmsproxy";
- private static final String MMS_PORT_COLUMN = "mmsport";
- private static final String PROXY_COLUMN = "proxy";
- private static final String MVNO_MATCH_DATA_COLUMN = "mvno_match_data";
- private static final String MVNO_TYPE_COLUMN = "mvno";
- private static final String AUTH_TYPE_COLUMN = "authtype";
- private static final String USER_COLUMN = "user";
- private static final String PASSWORD_COLUMN = "password";
- private static final String SERVER_COLUMN = "server";
-
- private static final String BASE_SELECTION = MCC_MNC_COLUMN + " = ?";
-
- private static ApnDatabase instance = null;
-
- public synchronized static ApnDatabase getInstance(Context context) throws IOException {
- if (instance == null) instance = new ApnDatabase(context.getApplicationContext());
- return instance;
- }
-
- private ApnDatabase(final Context context) throws IOException {
- this.context = context;
-
- File dbFile = context.getDatabasePath(DATABASE_NAME);
-
- if (!dbFile.getParentFile().exists() && !dbFile.getParentFile().mkdir()) {
- throw new IOException("couldn't make databases directory");
- }
-
- Util.copy(context.getAssets().open(ASSET_PATH, AssetManager.ACCESS_STREAMING),
- new FileOutputStream(dbFile));
-
- try {
- this.db = SQLiteDatabase.openDatabase(context.getDatabasePath(DATABASE_NAME).getPath(),
- null,
- SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
- } catch (SQLiteException e) {
- throw new IOException(e);
- }
- }
-
- private Apn getCustomApnParameters() {
- String mmsc = TextSecurePreferences.getMmscUrl(context).trim();
-
- if (!TextUtils.isEmpty(mmsc) && !mmsc.startsWith("http"))
- mmsc = "http://" + mmsc;
-
- String proxy = TextSecurePreferences.getMmscProxy(context);
- String port = TextSecurePreferences.getMmscProxyPort(context);
- String user = TextSecurePreferences.getMmscUsername(context);
- String pass = TextSecurePreferences.getMmscPassword(context);
-
- return new Apn(mmsc, proxy, port, user, pass);
- }
-
- public Apn getDefaultApnParameters(String mccmnc, String apn) {
- if (mccmnc == null) {
- Log.w(TAG, "mccmnc was null, returning null");
- return Apn.EMPTY;
- }
-
- Cursor cursor = null;
-
- try {
- if (apn != null) {
- Log.w(TAG, "Querying table for MCC+MNC " + mccmnc + " and APN name " + apn);
- cursor = db.query(TABLE_NAME, null,
- BASE_SELECTION + " AND " + APN_COLUMN + " = ?",
- new String[] {mccmnc, apn},
- null, null, null);
- }
-
- if (cursor == null || !cursor.moveToFirst()) {
- if (cursor != null) cursor.close();
- Log.w(TAG, "Querying table for MCC+MNC " + mccmnc + " without APN name");
- cursor = db.query(TABLE_NAME, null,
- BASE_SELECTION,
- new String[] {mccmnc},
- null, null, null);
- }
-
- if (cursor != null && cursor.moveToFirst()) {
- Apn params = new Apn(cursor.getString(cursor.getColumnIndexOrThrow(MMSC_COLUMN)),
- cursor.getString(cursor.getColumnIndexOrThrow(MMS_PROXY_COLUMN)),
- cursor.getString(cursor.getColumnIndexOrThrow(MMS_PORT_COLUMN)),
- cursor.getString(cursor.getColumnIndexOrThrow(USER_COLUMN)),
- cursor.getString(cursor.getColumnIndexOrThrow(PASSWORD_COLUMN)));
- Log.w(TAG, "Returning preferred APN " + params);
- return params;
- }
-
- Log.w(TAG, "No matching APNs found, returning null");
-
- return Apn.EMPTY;
- } finally {
- if (cursor != null) cursor.close();
- }
-
- }
-
- public Optional getMmsConnectionParameters(String mccmnc, String apn) {
- Apn customApn = getCustomApnParameters();
- Apn defaultApn = getDefaultApnParameters(mccmnc, apn);
- Apn result = new Apn(customApn, defaultApn,
- TextSecurePreferences.getUseCustomMmsc(context),
- TextSecurePreferences.getUseCustomMmscProxy(context),
- TextSecurePreferences.getUseCustomMmscProxyPort(context),
- TextSecurePreferences.getUseCustomMmscUsername(context),
- TextSecurePreferences.getUseCustomMmscPassword(context));
-
- if (TextUtils.isEmpty(result.getMmsc())) return Optional.absent();
- else return Optional.of(result);
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
deleted file mode 100644
index a1314be8d..000000000
--- a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import android.content.Context;
-import android.net.Uri;
-import android.support.annotation.Nullable;
-import android.util.Log;
-
-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.thoughtcrime.securesms.attachments.Attachment;
-import org.thoughtcrime.securesms.attachments.UriAttachment;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
-import org.thoughtcrime.securesms.database.Address;
-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.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
-import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
-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.notifications.MessageNotifier;
-import org.thoughtcrime.securesms.providers.SingleUseBlobProvider;
-import org.thoughtcrime.securesms.service.KeyCachingService;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
-import org.whispersystems.libsignal.DuplicateMessageException;
-import org.whispersystems.libsignal.InvalidMessageException;
-import org.whispersystems.libsignal.LegacyMessageException;
-import org.whispersystems.libsignal.NoSessionException;
-import org.whispersystems.libsignal.util.guava.Optional;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-public class MmsDownloadJob extends MasterSecretJob {
-
- private static final long serialVersionUID = 1L;
-
- private static final String TAG = MmsDownloadJob.class.getSimpleName();
-
- private final long messageId;
- private final long threadId;
- private final boolean automatic;
-
- public MmsDownloadJob(Context context, long messageId, long threadId, boolean automatic) {
- super(context, JobParameters.newBuilder()
- .withPersistence()
- .withRequirement(new MasterSecretRequirement(context))
- .withRequirement(new NetworkRequirement(context))
- .withGroupId("mms-operation")
- .withWakeLock(true, 30, TimeUnit.SECONDS)
- .create());
-
- this.messageId = messageId;
- this.threadId = threadId;
- this.automatic = automatic;
- }
-
- @Override
- public void onAdded() {
- if (automatic && KeyCachingService.getMasterSecret(context) == null) {
- DatabaseFactory.getMmsDatabase(context).markIncomingNotificationReceived(threadId);
- MessageNotifier.updateNotification(context);
- }
- }
-
- @Override
- public void onRun(MasterSecret masterSecret) {
- MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
- Optional 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.w(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);
- } catch (DuplicateMessageException e) {
- Log.w(TAG, e);
- database.markAsDecryptDuplicate(messageId, threadId);
- } catch (LegacyMessageException e) {
- Log.w(TAG, e);
- database.markAsLegacyVersion(messageId, threadId);
- } catch (NoSessionException e) {
- Log.w(TAG, e);
- database.markAsNoSession(messageId, threadId);
- } catch (InvalidMessageException e) {
- Log.w(TAG, e);
- database.markAsDecryptFailed(messageId, threadId);
- }
- }
-
- @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 onShouldRetryThrowable(Exception exception) {
- return false;
- }
-
- private void storeRetrievedMms(String contentLocation,
- long messageId, long threadId, RetrieveConf retrieved,
- int subscriptionId, @Nullable Address notificationFrom)
- throws MmsException, NoSessionException, DuplicateMessageException, InvalidMessageException,
- LegacyMessageException
- {
- MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
- SingleUseBlobProvider provider = SingleUseBlobProvider.getInstance();
- Optional group = Optional.absent();
- Set members = new HashSet<>();
- String body = null;
- List 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.UNKNOWN;
- }
-
- 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 2) {
- group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), true)));
- }
-
- IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false);
- Optional 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);
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
deleted file mode 100644
index a5ea75b98..000000000
--- a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import android.content.Context;
-import android.util.Log;
-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.thoughtcrime.securesms.database.Address;
-import org.thoughtcrime.securesms.database.DatabaseFactory;
-import org.thoughtcrime.securesms.database.MmsDatabase;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.util.Util;
-
-public class MmsReceiveJob extends ContextJob {
-
- private static final long serialVersionUID = 1L;
-
- private static final String TAG = MmsReceiveJob.class.getSimpleName();
-
- private final byte[] data;
- private final int subscriptionId;
-
- public MmsReceiveJob(Context context, byte[] data, int subscriptionId) {
- super(context, JobParameters.newBuilder()
- .withWakeLock(true)
- .withPersistence().create());
-
- this.data = data;
- this.subscriptionId = subscriptionId;
- }
-
- @Override
- public void onAdded() {
-
- }
-
- @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 messageAndThreadId = database.insertMessageInbox((NotificationInd)pdu, subscriptionId);
-
- Log.w(TAG, "Inserted received MMS notification...");
-
- ApplicationContext.getInstance(context)
- .getJobManager()
- .add(new MmsDownloadJob(context,
- 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(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;
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
deleted file mode 100644
index 8e561be02..000000000
--- a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.Log;
-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.thoughtcrime.securesms.attachments.Attachment;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
-import org.thoughtcrime.securesms.database.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.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
-import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
-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.thoughtcrime.securesms.notifications.MessageNotifier;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
-import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
-import org.thoughtcrime.securesms.util.Hex;
-import org.thoughtcrime.securesms.util.NumberUtil;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-
-public class MmsSendJob extends SendJob {
-
- private static final long serialVersionUID = 0L;
-
- private static final String TAG = MmsSendJob.class.getSimpleName();
-
- private final long messageId;
-
- public MmsSendJob(Context context, long messageId) {
- super(context, JobParameters.newBuilder()
- .withGroupId("mms-operation")
- .withRequirement(new NetworkRequirement(context))
- .withRequirement(new MasterSecretRequirement(context))
- .withPersistence()
- .create());
-
- this.messageId = messageId;
- }
-
- @Override
- public void onAdded() {
-
- }
-
- @Override
- public void onSend(MasterSecret masterSecret) throws MmsException, NoSuchMessageException, IOException {
- MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
- OutgoingMediaMessage message = database.getOutgoingMessage(messageId);
-
- try {
- 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());
- } 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 onShouldRetryThrowable(Exception exception) {
- return false;
- }
-
- @Override
- public void onCanceled() {
- 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.w(TAG, "Comparing: " + Hex.toString(message.getTransactionId()));
- Log.w(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 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 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) {
- MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
- }
- }
-
- private String getMyNumber(Context context) throws UndeliverableMessageException {
- try {
- return Utils.getMyPhoneNumber(context);
- } catch (SecurityException e) {
- throw new UndeliverableMessageException(e);
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
deleted file mode 100644
index a2ba460b9..000000000
--- a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
+++ /dev/null
@@ -1,208 +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 android.telephony.PhoneNumberUtils;
-import android.telephony.SmsManager;
-import android.util.Log;
-
-import org.thoughtcrime.securesms.crypto.MasterSecret;
-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.jobs.requirements.MasterSecretRequirement;
-import org.thoughtcrime.securesms.jobs.requirements.NetworkOrServiceRequirement;
-import org.thoughtcrime.securesms.jobs.requirements.ServiceRequirement;
-import org.thoughtcrime.securesms.notifications.MessageNotifier;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.service.SmsDeliveryListener;
-import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
-import org.thoughtcrime.securesms.util.NumberUtil;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-
-import java.util.ArrayList;
-
-public class SmsSendJob extends SendJob {
-
- private static final long serialVersionUID = -5118520036244759718L;
- private static final String TAG = SmsSendJob.class.getSimpleName();
-
- private final long messageId;
-
- public SmsSendJob(Context context, long messageId, String name) {
- super(context, constructParameters(context, name));
- this.messageId = messageId;
- }
-
- @Override
- public void onAdded() {}
-
- @Override
- public void onSend(MasterSecret masterSecret) throws NoSuchMessageException {
- SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
- SmsMessageRecord record = database.getMessage(messageId);
-
- try {
- Log.w(TAG, "Sending message: " + messageId);
-
- deliver(record);
- } catch (UndeliverableMessageException ude) {
- Log.w(TAG, ude);
- DatabaseFactory.getSmsDatabase(context).markAsSentFailed(record.getId());
- MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
- }
- }
-
- @Override
- public boolean onShouldRetryThrowable(Exception throwable) {
- return false;
- }
-
- @Override
- public void onCanceled() {
- Log.w(TAG, "onCanceled()");
- long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
- Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
-
- DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
- 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 messages = SmsManager.getDefault().divideMessage(message.getBody());
- ArrayList sentIntents = constructSentIntents(message.getId(), message.getType(), messages, false);
- ArrayList 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) {
- Log.w(TAG, npe);
- Log.w(TAG, "Recipient: " + recipient);
- Log.w(TAG, "Message Parts: " + messages.size());
-
- try {
- for (int i=0;i constructSentIntents(long messageId, long type,
- ArrayList messages, boolean secure)
- {
- ArrayList 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 constructDeliveredIntents(long messageId, long type, ArrayList messages) {
- if (!TextSecurePreferences.isSmsDeliveryReportsEnabled(context)) {
- return null;
- }
-
- ArrayList 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("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 JobParameters constructParameters(Context context, String name) {
- JobParameters.Builder builder = JobParameters.newBuilder()
- .withPersistence()
- .withRequirement(new MasterSecretRequirement(context))
- .withRetryCount(15)
- .withGroupId(name);
-
- if (TextSecurePreferences.isWifiSmsEnabled(context)) {
- builder.withRequirement(new NetworkOrServiceRequirement(context));
- } else {
- builder.withRequirement(new ServiceRequirement(context));
- }
-
- return builder.create();
- }
-
-
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java
deleted file mode 100644
index 1d26dcdc4..000000000
--- a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import android.app.Activity;
-import android.content.Context;
-import android.telephony.SmsManager;
-import android.util.Log;
-
-import org.thoughtcrime.securesms.ApplicationContext;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
-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.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
-import org.thoughtcrime.securesms.notifications.MessageNotifier;
-import org.thoughtcrime.securesms.service.SmsDeliveryListener;
-
-public class SmsSentJob extends MasterSecretJob {
-
- private static final long serialVersionUID = -2624694558755317560L;
- private static final String TAG = SmsSentJob.class.getSimpleName();
-
- private final long messageId;
- private final String action;
- private final int result;
-
- public SmsSentJob(Context context, long messageId, String action, int result) {
- super(context, JobParameters.newBuilder()
- .withPersistence()
- .withRequirement(new MasterSecretRequirement(context))
- .create());
-
- this.messageId = messageId;
- this.action = action;
- this.result = result;
- }
-
- @Override
- public void onAdded() {
-
- }
-
- @Override
- public void onRun(MasterSecret masterSecret) {
- Log.w(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 onShouldRetryThrowable(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()));
- break;
- default:
- database.markAsSentFailed(messageId);
- MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
- }
- } catch (NoSuchMessageException e) {
- Log.w(TAG, e);
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java b/src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java
deleted file mode 100644
index 64f36f59c..000000000
--- a/src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.thoughtcrime.securesms.mms;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.Build.VERSION;
-import android.os.Build.VERSION_CODES;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.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.w(TAG, "Sending via Lollipop API");
- return new OutgoingLollipopMmsConnection(context).send(pduBytes, subscriptionId);
- } catch (UndeliverableMessageException e) {
- Log.w(TAG, e);
- }
-
- Log.w(TAG, "Falling back to legacy connection...");
- }
-
- if (subscriptionId == -1) {
- Log.w(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.w(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.w(TAG, "Receiving via Lollipop API");
- try {
- return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
- } catch (MmsException e) {
- Log.w(TAG, e);
- }
-
- Log.w(TAG, "Falling back to receiving via legacy connection");
- }
-
- if (VERSION.SDK_INT < 22 || subscriptionId == -1) {
- Log.w(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.w(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...");
- }
-}
diff --git a/src/org/thoughtcrime/securesms/mms/IncomingLegacyMmsConnection.java b/src/org/thoughtcrime/securesms/mms/IncomingLegacyMmsConnection.java
deleted file mode 100644
index b184ce360..000000000
--- a/src/org/thoughtcrime/securesms/mms/IncomingLegacyMmsConnection.java
+++ /dev/null
@@ -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 .
- */
-package org.thoughtcrime.securesms.mms;
-
-import android.content.Context;
-import android.net.Uri;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.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.w(TAG, "Connecting directly...");
- try {
- return retrieve(contentApn, transactionId, false, false);
- } catch (IOException | ApnUnavailableException e) {
- Log.w(TAG, e);
- }
- }
-
- Log.w(TAG, "Changing radio to MMS mode..");
- radio.connect();
-
- try {
- Log.w(TAG, "Downloading in MMS mode with proxy...");
-
- try {
- return retrieve(contentApn, transactionId, true, true);
- } catch (IOException | ApnUnavailableException e) {
- Log.w(TAG, e);
- }
-
- Log.w(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.w(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);
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/mms/LegacyMmsConnection.java b/src/org/thoughtcrime/securesms/mms/LegacyMmsConnection.java
deleted file mode 100644
index d65f3a34c..000000000
--- a/src/org/thoughtcrime/securesms/mms/LegacyMmsConnection.java
+++ /dev/null
@@ -1,296 +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 .
- */
-package org.thoughtcrime.securesms.mms;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-
-import org.apache.http.Header;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.impl.NoConnectionReuseStrategyHC4;
-import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.impl.client.LaxRedirectStrategy;
-import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
-import org.apache.http.message.BasicHeader;
-import org.thoughtcrime.securesms.database.ApnDatabase;
-import org.thoughtcrime.securesms.util.ServiceUtil;
-import org.thoughtcrime.securesms.util.TelephonyUtil;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
-import org.whispersystems.libsignal.util.guava.Optional;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.InetAddress;
-import java.net.URL;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-@SuppressWarnings("deprecation")
-public abstract class LegacyMmsConnection {
-
- public static final String USER_AGENT = "Android-Mms/2.0";
-
- private static final String TAG = LegacyMmsConnection.class.getSimpleName();
-
- protected final Context context;
- protected final Apn apn;
-
- protected LegacyMmsConnection(Context context) throws ApnUnavailableException {
- this.context = context;
- this.apn = getApn(context);
- }
-
- public static Apn getApn(Context context) throws ApnUnavailableException {
-
- try {
- Optional params = ApnDatabase.getInstance(context)
- .getMmsConnectionParameters(TelephonyUtil.getMccMnc(context),
- TelephonyUtil.getApn(context));
-
- if (!params.isPresent()) {
- throw new ApnUnavailableException("No parameters available from ApnDefaults.");
- }
-
- return params.get();
- } catch (IOException ioe) {
- throw new ApnUnavailableException("ApnDatabase threw an IOException", ioe);
- }
- }
-
- protected boolean isDirectConnect() {
- // We think Sprint supports direct connection over wifi/data, but not Verizon
- Set sprintMccMncs = new HashSet() {{
- add("312530");
- add("311880");
- add("311870");
- add("311490");
- add("310120");
- add("316010");
- add("312190");
- }};
-
- return ServiceUtil.getTelephonyManager(context).getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA &&
- sprintMccMncs.contains(TelephonyUtil.getMccMnc(context));
- }
-
- @SuppressWarnings("TryWithIdenticalCatches")
- protected static boolean checkRouteToHost(Context context, String host, boolean usingMmsRadio)
- throws IOException
- {
- InetAddress inetAddress = InetAddress.getByName(host);
- if (!usingMmsRadio) {
- if (inetAddress.isSiteLocalAddress()) {
- throw new IOException("RFC1918 address in non-MMS radio situation!");
- }
- Log.w(TAG, "returning vacuous success since MMS radio is not in use");
- return true;
- }
-
- if (inetAddress == null) {
- throw new IOException("Unable to lookup host: InetAddress.getByName() returned null.");
- }
-
- byte[] ipAddressBytes = inetAddress.getAddress();
- if (ipAddressBytes == null) {
- Log.w(TAG, "resolved IP address bytes are null, returning true to attempt a connection anyway.");
- return true;
- }
-
- Log.w(TAG, "Checking route to address: " + host + ", " + inetAddress.getHostAddress());
- ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
-
- try {
- final Method requestRouteMethod = manager.getClass().getMethod("requestRouteToHostAddress", Integer.TYPE, InetAddress.class);
- final boolean routeToHostObtained = (Boolean) requestRouteMethod.invoke(manager, MmsRadio.TYPE_MOBILE_MMS, inetAddress);
- Log.w(TAG, "requestRouteToHostAddress(" + inetAddress + ") -> " + routeToHostObtained);
- return routeToHostObtained;
- } catch (NoSuchMethodException nsme) {
- Log.w(TAG, nsme);
- } catch (IllegalAccessException iae) {
- Log.w(TAG, iae);
- } catch (InvocationTargetException ite) {
- Log.w(TAG, ite);
- }
-
- return false;
- }
-
- protected static byte[] parseResponse(InputStream is) throws IOException {
- InputStream in = new BufferedInputStream(is);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- Util.copy(in, baos);
-
- Log.w(TAG, "Received full server response, " + baos.size() + " bytes");
-
- return baos.toByteArray();
- }
-
- protected CloseableHttpClient constructHttpClient() throws IOException {
- RequestConfig config = RequestConfig.custom()
- .setConnectTimeout(20 * 1000)
- .setConnectionRequestTimeout(20 * 1000)
- .setSocketTimeout(20 * 1000)
- .setMaxRedirects(20)
- .build();
-
- URL mmsc = new URL(apn.getMmsc());
- CredentialsProvider credsProvider = new BasicCredentialsProvider();
-
- if (apn.hasAuthentication()) {
- credsProvider.setCredentials(new AuthScope(mmsc.getHost(), mmsc.getPort() > -1 ? mmsc.getPort() : mmsc.getDefaultPort()),
- new UsernamePasswordCredentials(apn.getUsername(), apn.getPassword()));
- }
-
- return HttpClients.custom()
- .setConnectionReuseStrategy(new NoConnectionReuseStrategyHC4())
- .setRedirectStrategy(new LaxRedirectStrategy())
- .setUserAgent(TextSecurePreferences.getMmsUserAgent(context, USER_AGENT))
- .setConnectionManager(new BasicHttpClientConnectionManager())
- .setDefaultRequestConfig(config)
- .setDefaultCredentialsProvider(credsProvider)
- .build();
- }
-
- protected byte[] execute(HttpUriRequest request) throws IOException {
- Log.w(TAG, "connecting to " + apn.getMmsc());
-
- CloseableHttpClient client = null;
- CloseableHttpResponse response = null;
- try {
- client = constructHttpClient();
- response = client.execute(request);
-
- Log.w(TAG, "* response code: " + response.getStatusLine());
-
- if (response.getStatusLine().getStatusCode() == 200) {
- return parseResponse(response.getEntity().getContent());
- }
- } catch (NullPointerException npe) {
- // TODO determine root cause
- // see: https://github.com/signalapp/Signal-Android/issues/4379
- throw new IOException(npe);
- } finally {
- if (response != null) response.close();
- if (client != null) client.close();
- }
-
- throw new IOException("unhandled response code");
- }
-
- protected List getBaseHeaders() {
- final String number = TelephonyUtil.getManager(context).getLine1Number(); ;
-
- return new LinkedList() {{
- add(new BasicHeader("Accept", "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic"));
- add(new BasicHeader("x-wap-profile", "http://www.google.com/oha/rdf/ua-profile-kila.xml"));
- add(new BasicHeader("Content-Type", "application/vnd.wap.mms-message"));
- add(new BasicHeader("x-carrier-magic", "http://magic.google.com"));
- if (!TextUtils.isEmpty(number)) {
- add(new BasicHeader("x-up-calling-line-id", number));
- add(new BasicHeader("X-MDN", number));
- }
- }};
- }
-
- public static class Apn {
-
- public static Apn EMPTY = new Apn("", "", "", "", "");
-
- private final String mmsc;
- private final String proxy;
- private final String port;
- private final String username;
- private final String password;
-
- public Apn(String mmsc, String proxy, String port, String username, String password) {
- this.mmsc = mmsc;
- this.proxy = proxy;
- this.port = port;
- this.username = username;
- this.password = password;
- }
-
- public Apn(Apn customApn, Apn defaultApn,
- boolean useCustomMmsc,
- boolean useCustomProxy,
- boolean useCustomProxyPort,
- boolean useCustomUsername,
- boolean useCustomPassword)
- {
- this.mmsc = useCustomMmsc ? customApn.mmsc : defaultApn.mmsc;
- this.proxy = useCustomProxy ? customApn.proxy : defaultApn.proxy;
- this.port = useCustomProxyPort ? customApn.port : defaultApn.port;
- this.username = useCustomUsername ? customApn.username : defaultApn.username;
- this.password = useCustomPassword ? customApn.password : defaultApn.password;
- }
-
- public boolean hasProxy() {
- return !TextUtils.isEmpty(proxy);
- }
-
- public String getMmsc() {
- return mmsc;
- }
-
- public String getProxy() {
- return hasProxy() ? proxy : null;
- }
-
- public int getPort() {
- return TextUtils.isEmpty(port) ? 80 : Integer.parseInt(port);
- }
-
- public boolean hasAuthentication() {
- return !TextUtils.isEmpty(username);
- }
-
- public String getUsername() {
- return username;
- }
-
- public String getPassword() {
- return password;
- }
-
- @Override
- public String toString() {
- return Apn.class.getSimpleName() +
- "{ mmsc: \"" + mmsc + "\"" +
- ", proxy: " + (proxy == null ? "none" : '"' + proxy + '"') +
- ", port: " + (port == null ? "(none)" : port) +
- ", user: " + (username == null ? "none" : '"' + username + '"') +
- ", pass: " + (password == null ? "none" : '"' + password + '"') + " }";
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/mms/OutgoingLegacyMmsConnection.java b/src/org/thoughtcrime/securesms/mms/OutgoingLegacyMmsConnection.java
deleted file mode 100644
index 4d9f36458..000000000
--- a/src/org/thoughtcrime/securesms/mms/OutgoingLegacyMmsConnection.java
+++ /dev/null
@@ -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 .
- */
-package org.thoughtcrime.securesms.mms;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.Uri;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.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.w(TAG, "Sending MMS directly without radio change...");
- try {
- return send(pduBytes, false, false);
- } catch (IOException e) {
- Log.w(TAG, e);
- }
- }
-
- Log.w(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.w(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.w(TAG, "Sending MMS of length: " + pduBytes.length
- + (useMmsRadio ? ", using mms radio" : "")
- + (useProxy ? ", using proxy" : ""));
-
- try {
- if (checkRouteToHost(context, targetHost, useMmsRadio)) {
- Log.w(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;
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/service/MmsListener.java b/src/org/thoughtcrime/securesms/service/MmsListener.java
deleted file mode 100644
index 3d8417d80..000000000
--- a/src/org/thoughtcrime/securesms/service/MmsListener.java
+++ /dev/null
@@ -1,78 +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 .
- */
-package org.thoughtcrime.securesms.service;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-import android.provider.Telephony;
-import android.util.Log;
-
-import org.thoughtcrime.securesms.ApplicationContext;
-import org.thoughtcrime.securesms.jobs.MmsReceiveJob;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
- Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION.equals(intent.getAction()) &&
- Util.isDefaultSmsProvider(context))
- {
- return false;
- }
-
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT &&
- TextSecurePreferences.isInterceptAllMmsEnabled(context))
- {
- return true;
- }
-
- return false;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.w(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.w(TAG, "Relevant!");
- int subscriptionId = intent.getExtras().getInt("subscription", -1);
-
- ApplicationContext.getInstance(context)
- .getJobManager()
- .add(new MmsReceiveJob(context, intent.getByteArrayExtra("data"), subscriptionId));
-
- abortBroadcast();
- }
- }
-
-
-
-}
diff --git a/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java b/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java
deleted file mode 100644
index a579f6236..000000000
--- a/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.thoughtcrime.securesms.service;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.telephony.SmsMessage;
-import android.util.Log;
-
-import org.thoughtcrime.securesms.ApplicationContext;
-import org.thoughtcrime.securesms.database.SmsDatabase;
-import org.thoughtcrime.securesms.jobmanager.JobManager;
-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);
-
- switch (intent.getAction()) {
- case SENT_SMS_ACTION:
- int result = getResultCode();
-
- jobManager.add(new SmsSentJob(context, messageId, SENT_SMS_ACTION, result));
- 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.w(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(context, messageId, DELIVERED_SMS_ACTION, status));
- break;
- default:
- Log.w(TAG, "Unknown action: " + intent.getAction());
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java
index bf769fe53..342a81a99 100644
--- a/src/org/thoughtcrime/securesms/sms/MessageSender.java
+++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java
@@ -17,7 +17,6 @@
package org.thoughtcrime.securesms.sms;
import android.content.Context;
-import android.database.Cursor;
import android.support.annotation.NonNull;
import android.util.Log;
import android.util.Pair;
@@ -34,11 +33,9 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
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.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.push.AccountManagerFactory;
@@ -209,13 +206,13 @@ public class MessageSender {
}
private static void sendSms(Context context, Recipient recipient, long messageId) {
- JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
- jobManager.add(new SmsSendJob(context, messageId, recipient.getName()));
+// 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(context, messageId));
+// JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
+// jobManager.add(new MmsSendJob(context, messageId));
}
private static boolean isPushTextSend(Context context, Recipient recipient, boolean keyExchange) {
diff --git a/src/org/thoughtcrime/securesms/util/MmsCharacterCalculator.java b/src/org/thoughtcrime/securesms/util/MmsCharacterCalculator.java
deleted file mode 100644
index 9d4698c20..000000000
--- a/src/org/thoughtcrime/securesms/util/MmsCharacterCalculator.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.thoughtcrime.securesms.util;
-
-public class MmsCharacterCalculator extends CharacterCalculator {
-
- private static final int MAX_SIZE = 5000;
-
- @Override
- public CharacterState calculateCharacters(String messageBody) {
- return new CharacterState(1, MAX_SIZE - messageBody.length(), MAX_SIZE);
- }
-}
diff --git a/src/org/thoughtcrime/securesms/util/SmsCharacterCalculator.java b/src/org/thoughtcrime/securesms/util/SmsCharacterCalculator.java
deleted file mode 100644
index a822641d1..000000000
--- a/src/org/thoughtcrime/securesms/util/SmsCharacterCalculator.java
+++ /dev/null
@@ -1,56 +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 .
- */
-package org.thoughtcrime.securesms.util;
-
-import android.telephony.SmsMessage;
-import android.util.Log;
-
-public class SmsCharacterCalculator extends CharacterCalculator {
-
- private static final String TAG = SmsCharacterCalculator.class.getSimpleName();
-
- @Override
- public CharacterState calculateCharacters(String messageBody) {
- int[] length;
- int messagesSpent;
- int charactersSpent;
- int charactersRemaining;
-
- try {
- length = SmsMessage.calculateLength(messageBody, false);
- messagesSpent = length[0];
- charactersSpent = length[1];
- charactersRemaining = length[2];
- } catch (NullPointerException e) {
- Log.w(TAG, e);
- messagesSpent = 1;
- charactersSpent = messageBody.length();
- charactersRemaining = 1000;
- }
-
- int maxMessageSize;
-
- if (messagesSpent > 0) {
- maxMessageSize = (charactersSpent + charactersRemaining) / messagesSpent;
- } else {
- maxMessageSize = (charactersSpent + charactersRemaining);
- }
-
- return new CharacterState(messagesSpent, charactersRemaining, maxMessageSize);
- }
-}
-
diff --git a/src/org/thoughtcrime/securesms/util/Util.java b/src/org/thoughtcrime/securesms/util/Util.java
index 79a62f44c..89c62587b 100644
--- a/src/org/thoughtcrime/securesms/util/Util.java
+++ b/src/org/thoughtcrime/securesms/util/Util.java
@@ -50,7 +50,6 @@ import com.google.i18n.phonenumbers.Phonenumber;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.components.ComposeText;
import org.thoughtcrime.securesms.database.Address;
-import org.thoughtcrime.securesms.mms.OutgoingLegacyMmsConnection;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.ByteArrayOutputStream;
@@ -374,11 +373,6 @@ public class Util {
return 90 - age;
}
- @TargetApi(VERSION_CODES.LOLLIPOP)
- public static boolean isMmsCapable(Context context) {
- return (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) || OutgoingLegacyMmsConnection.isConnectionPossible(context);
- }
-
public static boolean isMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
diff --git a/test/androidTest/java/org/thoughtcrime/securesms/TextSecureTestCase.java b/test/androidTest/java/org/thoughtcrime/securesms/TextSecureTestCase.java
deleted file mode 100644
index 0de79c8d4..000000000
--- a/test/androidTest/java/org/thoughtcrime/securesms/TextSecureTestCase.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.thoughtcrime.securesms;
-
-import android.content.Context;
-import android.test.InstrumentationTestCase;
-
-public class TextSecureTestCase extends InstrumentationTestCase {
-
- @Override
- public void setUp() {
- System.setProperty("dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath());
- }
-
- protected Context getContext() {
- return getInstrumentation().getContext();
- }
-}
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/BaseUnitTest.java b/test/unitTest/java/org/thoughtcrime/securesms/BaseUnitTest.java
deleted file mode 100644
index 41d35df43..000000000
--- a/test/unitTest/java/org/thoughtcrime/securesms/BaseUnitTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.thoughtcrime.securesms;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Handler;
-import android.os.Looper;
-import android.preference.PreferenceManager;
-import android.text.TextUtils;
-import android.util.Log;
-
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyFloat;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.powermock.api.mockito.PowerMockito.mock;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
-import static org.powermock.api.mockito.PowerMockito.when;
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ Log.class, Handler.class, Looper.class, TextUtils.class, PreferenceManager.class })
-public abstract class BaseUnitTest {
-
- protected Context context = mock(Context.class);
- protected SharedPreferences sharedPreferences = mock(SharedPreferences.class);
-
- @Before
- public void setUp() throws Exception {
- mockStatic(Looper.class);
- mockStatic(Log.class);
- mockStatic(Handler.class);
- mockStatic(TextUtils.class);
- mockStatic(PreferenceManager.class);
-
- when(PreferenceManager.getDefaultSharedPreferences(any(Context.class))).thenReturn(sharedPreferences);
- when(Looper.getMainLooper()).thenReturn(null);
- PowerMockito.whenNew(Handler.class).withAnyArguments().thenReturn(null);
-
- Answer> logAnswer = new Answer() {
- @Override public Void answer(InvocationOnMock invocation) throws Throwable {
- final String tag = (String)invocation.getArguments()[0];
- final String msg = (String)invocation.getArguments()[1];
- System.out.println(invocation.getMethod().getName().toUpperCase() + "/[" + tag + "] " + msg);
- return null;
- }
- };
- PowerMockito.doAnswer(logAnswer).when(Log.class, "d", anyString(), anyString());
- PowerMockito.doAnswer(logAnswer).when(Log.class, "i", anyString(), anyString());
- PowerMockito.doAnswer(logAnswer).when(Log.class, "w", anyString(), anyString());
- PowerMockito.doAnswer(logAnswer).when(Log.class, "e", anyString(), anyString());
- PowerMockito.doAnswer(logAnswer).when(Log.class, "wtf", anyString(), anyString());
-
- PowerMockito.doAnswer(new Answer() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- final String s = (String)invocation.getArguments()[0];
- return s == null || s.length() == 0;
- }
- }).when(TextUtils.class, "isEmpty", anyString());
-
- when(sharedPreferences.getString(anyString(), anyString())).thenReturn("");
- when(sharedPreferences.getLong(anyString(), anyLong())).thenReturn(0L);
- when(sharedPreferences.getInt(anyString(), anyInt())).thenReturn(0);
- when(sharedPreferences.getBoolean(anyString(), anyBoolean())).thenReturn(false);
- when(sharedPreferences.getFloat(anyString(), anyFloat())).thenReturn(0f);
- when(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPreferences);
- when(context.getPackageName()).thenReturn("org.thoughtcrime.securesms");
- }
-}
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/database/AddressTest.java b/test/unitTest/java/org/thoughtcrime/securesms/database/AddressTest.java
deleted file mode 100644
index be6ec02e4..000000000
--- a/test/unitTest/java/org/thoughtcrime/securesms/database/AddressTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.thoughtcrime.securesms.database;
-
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static junit.framework.Assert.assertEquals;
-
-public class AddressTest {
-
- @Before
- public void setup() {}
-
- @Test
- public void testAddressString() throws Exception {
- Address.ExternalAddressFormatter formatter = new Address.ExternalAddressFormatter("+14152222222");
- assertEquals(formatter.format("bonbon"), "bonbon");
- }
-
- @Test
- public void testAddressShortCode() throws Exception {
- Address.ExternalAddressFormatter formatter = new Address.ExternalAddressFormatter("+14152222222");
- assertEquals(formatter.format("40404"), "40404");
- }
-
- @Test
- public void testEmailAddress() throws Exception {
- Address.ExternalAddressFormatter formatter = new Address.ExternalAddressFormatter("+14152222222");
- assertEquals(formatter.format("junk@junk.net"), "junk@junk.net");
- }
-
- @Test
- public void testNumberArbitrary() throws Exception {
- Address.ExternalAddressFormatter formatter = new Address.ExternalAddressFormatter("+14152222222");
- assertEquals(formatter.format("(415) 111-1122"), "+14151111122");
- assertEquals(formatter.format("(415) 111 1123"), "+14151111123");
- assertEquals(formatter.format("415-111-1124"), "+14151111124");
- assertEquals(formatter.format("415.111.1125"), "+14151111125");
- assertEquals(formatter.format("+1 415.111.1126"), "+14151111126");
- assertEquals(formatter.format("+1 415 111 1127"), "+14151111127");
- assertEquals(formatter.format("+1 (415) 111 1128"), "+14151111128");
-
- formatter = new Address.ExternalAddressFormatter("+442079460010");
- assertEquals(formatter.format("(020) 7946 0018"), "+442079460018");
- }
-
- @Test
- public void testGroup() throws Exception {
- Address.ExternalAddressFormatter formatter = new Address.ExternalAddressFormatter("+14152222222");
- assertEquals(formatter.format("__textsecure_group__!foobar"), "__textsecure_group__!foobar");
- }
-
- @Test
- public void testLostLocalNumber() throws Exception {
- Address.ExternalAddressFormatter formatter = new Address.ExternalAddressFormatter("US", true);
- assertEquals(formatter.format("(415) 111-1122"), "+14151111122");
- }
-
-}
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/database/CursorRecyclerViewAdapterTest.java b/test/unitTest/java/org/thoughtcrime/securesms/database/CursorRecyclerViewAdapterTest.java
deleted file mode 100644
index ec61223c3..000000000
--- a/test/unitTest/java/org/thoughtcrime/securesms/database/CursorRecyclerViewAdapterTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.thoughtcrime.securesms.database;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.view.View;
-import android.view.ViewGroup;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class CursorRecyclerViewAdapterTest {
- private CursorRecyclerViewAdapter adapter;
- private Context context;
- private Cursor cursor;
-
- @Before
- public void setUp() {
- context = mock(Context.class);
- cursor = mock(Cursor.class);
- when(cursor.getCount()).thenReturn(100);
- when(cursor.moveToPosition(anyInt())).thenReturn(true);
-
- adapter = new CursorRecyclerViewAdapter(context, cursor) {
- @Override
- public ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
- return null;
- }
-
- @Override
- public void onBindItemViewHolder(ViewHolder viewHolder, @NonNull Cursor cursor) {
- }
- };
- }
-
- @Test
- public void testSanityCount() throws Exception {
- assertEquals(adapter.getItemCount(), 100);
- }
-
- @Test
- public void testHeaderCount() throws Exception {
- adapter.setHeaderView(new View(context));
- assertEquals(adapter.getItemCount(), 101);
-
- assertEquals(adapter.getItemViewType(0), CursorRecyclerViewAdapter.HEADER_TYPE);
- assertNotEquals(adapter.getItemViewType(1), CursorRecyclerViewAdapter.HEADER_TYPE);
- assertNotEquals(adapter.getItemViewType(100), CursorRecyclerViewAdapter.HEADER_TYPE);
- }
-
- @Test
- public void testFooterCount() throws Exception {
- adapter.setFooterView(new View(context));
- assertEquals(adapter.getItemCount(), 101);
- assertEquals(adapter.getItemViewType(100), CursorRecyclerViewAdapter.FOOTER_TYPE);
- assertNotEquals(adapter.getItemViewType(0), CursorRecyclerViewAdapter.FOOTER_TYPE);
- assertNotEquals(adapter.getItemViewType(99), CursorRecyclerViewAdapter.FOOTER_TYPE);
- }
-
- @Test
- public void testHeaderFooterCount() throws Exception {
- adapter.setHeaderView(new View(context));
- adapter.setFooterView(new View(context));
- assertEquals(adapter.getItemCount(), 102);
- assertEquals(adapter.getItemViewType(101), CursorRecyclerViewAdapter.FOOTER_TYPE);
- assertEquals(adapter.getItemViewType(0), CursorRecyclerViewAdapter.HEADER_TYPE);
- assertNotEquals(adapter.getItemViewType(1), CursorRecyclerViewAdapter.HEADER_TYPE);
- assertNotEquals(adapter.getItemViewType(100), CursorRecyclerViewAdapter.FOOTER_TYPE);
- }
-}
-
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/service/SmsListenerTest.java b/test/unitTest/java/org/thoughtcrime/securesms/service/SmsListenerTest.java
deleted file mode 100644
index 6f16602cc..000000000
--- a/test/unitTest/java/org/thoughtcrime/securesms/service/SmsListenerTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.thoughtcrime.securesms.service;
-
-import junit.framework.AssertionFailedError;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.thoughtcrime.securesms.BaseUnitTest;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.contains;
-import static org.mockito.Mockito.when;
-
-public class SmsListenerTest extends BaseUnitTest {
- private static Map CHALLENGES = new HashMap() {{
- put("Your TextSecure verification code: 337-337", "337337");
- put("XXX\nYour TextSecure verification code: 1337-1337", "13371337");
- put("Your TextSecure verification code: 337-1337", "3371337");
- put("Your TextSecure verification code: 1337-337", "1337337");
- put("Your TextSecure verification code: 1337-1337", "13371337");
- put("XXXYour TextSecure verification code: 1337-1337", "13371337");
- put("Your TextSecure verification code: 1337-1337XXX", "13371337");
- put("Your TextSecure verification code 1337-1337", "13371337");
-
- put("Your Signal verification code: 337-337", "337337");
- put("XXX\nYour Signal verification code: 1337-1337", "13371337");
- put("Your Signal verification code: 337-1337", "3371337");
- put("Your Signal verification code: 1337-337", "1337337");
- put("Your Signal verification code: 1337-1337", "13371337");
- put("XXXYour Signal verification code: 1337-1337", "13371337");
- put("Your Signal verification code: 1337-1337XXX", "13371337");
- put("Your Signal verification code 1337-1337", "13371337");
- }};
-
- private SmsListener listener;
-
- @Before
- @Override
- public void setUp() throws Exception {
- super.setUp();
- listener = new SmsListener();
- when(sharedPreferences.getBoolean(contains("pref_verifying"), anyBoolean())).thenReturn(true);
- }
-
- @Test
- public void testChallenges() throws Exception {
- for (Entry challenge : CHALLENGES.entrySet()) {
- if (!listener.isChallenge(context, challenge.getKey())) {
- throw new AssertionFailedError("SmsListener didn't recognize body as a challenge.");
- }
- assertEquals(listener.parseChallenge(challenge.getKey()), challenge.getValue());
- }
- }
-}
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/util/DelimiterUtilTest.java b/test/unitTest/java/org/thoughtcrime/securesms/util/DelimiterUtilTest.java
deleted file mode 100644
index 8d7a25e88..000000000
--- a/test/unitTest/java/org/thoughtcrime/securesms/util/DelimiterUtilTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.thoughtcrime.securesms.util;
-
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static junit.framework.Assert.assertEquals;
-
-public class DelimiterUtilTest {
-
- @Before
- public void setup() {}
-
- @Test
- public void testEscape() {
- assertEquals(DelimiterUtil.escape("MTV Music", ' '), "MTV\\ Music");
- assertEquals(DelimiterUtil.escape("MTV Music", ' '), "MTV\\ \\ Music");
-
- assertEquals(DelimiterUtil.escape("MTV,Music", ','), "MTV\\,Music");
- assertEquals(DelimiterUtil.escape("MTV,,Music", ','), "MTV\\,\\,Music");
-
- assertEquals(DelimiterUtil.escape("MTV Music", '+'), "MTV Music");
- }
-
- @Test
- public void testSplit() {
- String[] parts = DelimiterUtil.split("MTV\\ Music", ' ');
- assertEquals(parts.length, 1);
- assertEquals(parts[0], "MTV\\ Music");
-
- parts = DelimiterUtil.split("MTV Music", ' ');
- assertEquals(parts.length, 2);
- assertEquals(parts[0], "MTV");
- assertEquals(parts[1], "Music");
- }
-
- @Test
- public void testEscapeSplit() {
- String input = "MTV Music";
- String intermediate = DelimiterUtil.escape(input, ' ');
- String[] parts = DelimiterUtil.split(intermediate, ' ');
-
- assertEquals(parts.length, 1);
- assertEquals(parts[0], "MTV\\ Music");
- assertEquals(DelimiterUtil.unescape(parts[0], ' '), "MTV Music");
-
- input = "MTV\\ Music";
- intermediate = DelimiterUtil.escape(input, ' ');
- parts = DelimiterUtil.split(intermediate, ' ');
-
- assertEquals(parts.length, 1);
- assertEquals(parts[0], "MTV\\\\ Music");
- assertEquals(DelimiterUtil.unescape(parts[0], ' '), "MTV\\ Music");
- }
-
-}
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/util/ListPartitionTest.java b/test/unitTest/java/org/thoughtcrime/securesms/util/ListPartitionTest.java
deleted file mode 100644
index 1ef955a83..000000000
--- a/test/unitTest/java/org/thoughtcrime/securesms/util/ListPartitionTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.thoughtcrime.securesms.util;
-
-import org.junit.Test;
-import org.thoughtcrime.securesms.BaseUnitTest;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class ListPartitionTest extends BaseUnitTest {
-
- @Test public void testPartitionEven() {
- List list = new LinkedList<>();
-
- for (int i=0;i<100;i++) {
- list.add(i);
- }
-
- List> partitions = Util.partition(list, 10);
-
- assertEquals(partitions.size(), 10);
-
- int counter = 0;
-
- for (int i=0;i partition = partitions.get(i);
- assertEquals(partition.size(), 10);
-
- for (int j=0;j list = new LinkedList<>();
-
- for (int i=0;i<100;i++) {
- list.add(i);
- }
-
- list.add(100);
-
- List> partitions = Util.partition(list, 10);
-
- assertEquals(partitions.size(), 11);
-
- int counter = 0;
-
- for (int i=0;i partition = partitions.get(i);
- assertEquals(partition.size(), 10);
-
- for (int j=0;j list = new LinkedList<>();
-
- for (int i=0;i<100;i++) {
- list.add(i);
- }
-
- List> partitions = Util.partition(list, 1);
-
- assertEquals(partitions.size(), 100);
-
- int counter = 0;
-
- for (int i=0;i partition = partitions.get(i);
- assertEquals(partition.size(), 1);
-
- for (int j=0;j.
- */
-
-package org.thoughtcrime.securesms.util;
-
-import junit.framework.AssertionFailedError;
-
-import org.junit.Test;
-import org.thoughtcrime.securesms.BaseUnitTest;
-
-import java.net.URISyntaxException;
-
-import static org.junit.Assert.assertTrue;
-
-public class Rfc5724UriTest extends BaseUnitTest {
-
- @Test public void testInvalidPath() throws Exception {
- final String[] invalidSchemaUris = {
- "",
- ":",
- "sms:",
- ":sms",
- "sms:?goto=fail",
- "sms:?goto=fail&fail=goto"
- };
-
- for (String uri : invalidSchemaUris) {
- try {
- new Rfc5724Uri(uri);
- throw new AssertionFailedError("URISyntaxException should be thrown");
- } catch (URISyntaxException e) {
- // success
- }
- }
- }
-
- @Test public void testGetSchema() throws Exception {
- final String[][] uriTestPairs = {
- {"sms:+15555555555", "sms"},
- {"sMs:+15555555555", "sMs"},
- {"smsto:+15555555555?", "smsto"},
- {"mms:+15555555555?a=b", "mms"},
- {"mmsto:+15555555555?a=b&c=d", "mmsto"}
- };
-
- for (String[] uriTestPair : uriTestPairs) {
- final Rfc5724Uri testUri = new Rfc5724Uri(uriTestPair[0]);
- assertTrue(testUri.getSchema().equals(uriTestPair[1]));
- }
- }
-
- @Test public void testGetPath() throws Exception {
- final String[][] uriTestPairs = {
- {"sms:+15555555555", "+15555555555"},
- {"sms:%2B555555555", "%2B555555555"},
- {"smsto:+15555555555?", "+15555555555"},
- {"mms:+15555555555?a=b", "+15555555555"},
- {"mmsto:+15555555555?a=b&c=d", "+15555555555"},
- {"sms:+15555555555,+14444444444", "+15555555555,+14444444444"},
- {"sms:+15555555555,+14444444444?", "+15555555555,+14444444444"},
- {"sms:+15555555555,+14444444444?a=b", "+15555555555,+14444444444"},
- {"sms:+15555555555,+14444444444?a=b&c=d", "+15555555555,+14444444444"}
- };
-
- for (String[] uriTestPair : uriTestPairs) {
- final Rfc5724Uri testUri = new Rfc5724Uri(uriTestPair[0]);
- assertTrue(testUri.getPath().equals(uriTestPair[1]));
- }
- }
-
- @Test public void testGetQueryParams() throws Exception {
- final String[][] uriTestPairs = {
- {"sms:+15555555555", "a", null},
- {"mms:+15555555555?b=", "a", null},
- {"mmsto:+15555555555?a=", "a", ""},
- {"sms:+15555555555?a=b", "a", "b"},
- {"sms:+15555555555?a=b&c=d", "a", "b"},
- {"sms:+15555555555?a=b&c=d", "b", null},
- {"sms:+15555555555?a=b&c=d", "c", "d"},
- {"sms:+15555555555?a=b&c=d", "d", null}
- };
-
- for (String[] uriTestPair : uriTestPairs) {
- final Rfc5724Uri testUri = new Rfc5724Uri(uriTestPair[0]);
- final String paramResult = testUri.getQueryParams().get(uriTestPair[1]);
-
- if (paramResult == null) assertTrue(uriTestPair[2] == null);
- else assertTrue(paramResult.equals(uriTestPair[2]));
- }
- }
-}
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/util/ShortCodeUtilTest.java b/test/unitTest/java/org/thoughtcrime/securesms/util/ShortCodeUtilTest.java
deleted file mode 100644
index f6ebf685c..000000000
--- a/test/unitTest/java/org/thoughtcrime/securesms/util/ShortCodeUtilTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.thoughtcrime.securesms.util;
-
-import org.junit.Test;
-
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-public class ShortCodeUtilTest {
-
- @Test
- public void testShortCodes() throws Exception {
- assertTrue(ShortCodeUtil.isShortCode("+14152222222", "40404"));
- assertTrue(ShortCodeUtil.isShortCode("+14152222222", "431"));
- assertFalse(ShortCodeUtil.isShortCode("+14152222222", "4157778888"));
- assertFalse(ShortCodeUtil.isShortCode("+14152222222", "+14157778888"));
- assertFalse(ShortCodeUtil.isShortCode("+14152222222", "415-777-8888"));
- assertFalse(ShortCodeUtil.isShortCode("+14152222222", "(415) 777-8888"));
- assertFalse(ShortCodeUtil.isShortCode("+14152222222", "8882222"));
- assertFalse(ShortCodeUtil.isShortCode("+14152222222", "888-2222"));
-
- assertTrue(ShortCodeUtil.isShortCode("+491723742522", "670"));
- assertTrue(ShortCodeUtil.isShortCode("+491723742522", "115"));
- assertFalse(ShortCodeUtil.isShortCode("+491723742522", "089-12345678"));
- assertFalse(ShortCodeUtil.isShortCode("+491723742522", "089/12345678"));
- assertFalse(ShortCodeUtil.isShortCode("+491723742522", "12345678"));
-
- assertTrue(ShortCodeUtil.isShortCode("+298123456", "4040"));
- assertTrue(ShortCodeUtil.isShortCode("+298123456", "6701"));
- assertTrue(ShortCodeUtil.isShortCode("+298123456", "433"));
- assertFalse(ShortCodeUtil.isShortCode("+298123456", "123456"));
-
- assertTrue(ShortCodeUtil.isShortCode("+61414915066", "19808948"));
- assertFalse(ShortCodeUtil.isShortCode("+61414915066", "119808948"));
-
- assertTrue(ShortCodeUtil.isShortCode("+79166503388", "8080"));
- assertTrue(ShortCodeUtil.isShortCode("+79166503388", "6701"));
- assertTrue(ShortCodeUtil.isShortCode("+79166503388", "431"));
- assertFalse(ShortCodeUtil.isShortCode("+79166503388", "111-22-33"));
- }
-
-}