remove dead code

This commit is contained in:
B. Petersen
2018-12-09 02:33:41 +01:00
parent b34cbc2b88
commit b166f1e4fd
18 changed files with 0 additions and 986 deletions
@@ -16,16 +16,11 @@ import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import com.google.i18n.phonenumbers.ShortNumberInfo;
import org.thoughtcrime.securesms.util.DelimiterUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.NumberUtil;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
@@ -78,29 +73,6 @@ public class Address implements Parcelable, Comparable<Address> {
return new Address(getExternalAddressFormatter(context).format(external));
}
public static @NonNull List<Address> fromSerializedList(@NonNull String serialized, char delimiter) {
String[] escapedAddresses = DelimiterUtil.split(serialized, delimiter);
List<Address> addresses = new LinkedList<>();
for (String escapedAddress : escapedAddresses) {
addresses.add(Address.fromSerialized(DelimiterUtil.unescape(escapedAddress, delimiter)));
}
return addresses;
}
public static @NonNull String toSerializedList(@NonNull List<Address> addresses, char delimiter) {
Collections.sort(addresses);
List<String> escapedAddresses = new LinkedList<>();
for (Address address : addresses) {
escapedAddresses.add(DelimiterUtil.escape(address.serialize(), delimiter));
}
return Util.join(escapedAddresses, delimiter + "");
}
private static @NonNull ExternalAddressFormatter getExternalAddressFormatter(Context context) {
String localNumber = Prefs.getLocalNumber(context);
@@ -138,11 +110,6 @@ public class Address implements Parcelable, Comparable<Address> {
public boolean isDcContact() { return address.startsWith(DC_CONTACT_PREFIX); };
public @NonNull String toGroupString() {
if (!isGroup()) throw new AssertionError("Not group: " + address);
return address;
}
public @NonNull String toPhoneString() {
if (!isPhone()) throw new AssertionError("Not e164: " + address);
return address;
@@ -16,19 +16,13 @@
*/
package org.thoughtcrime.securesms.database;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import net.sqlcipher.database.SQLiteDatabase;
@@ -39,26 +33,15 @@ import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.util.JsonUtils;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.MediaUtil.ThumbnailData;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.video.EncryptedMediaDataSource;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
public class AttachmentDatabase extends Database {
@@ -77,7 +60,6 @@ public class AttachmentDatabase extends Database {
public static final String SIZE = "data_size";
static final String FILE_NAME = "file_name";
public static final String THUMBNAIL = "thumbnail";
static final String THUMBNAIL_ASPECT_RATIO = "aspect_ratio";
public static final String UNIQUE_ID = "unique_id";
static final String DIGEST = "digest";
static final String VOICE_NOTE = "voice_note";
@@ -88,41 +70,12 @@ public class AttachmentDatabase extends Database {
static final String WIDTH = "width";
static final String HEIGHT = "height";
public static final String DIRECTORY = "parts";
public static final int TRANSFER_PROGRESS_DONE = 0;
public static final int TRANSFER_PROGRESS_STARTED = 1;
public static final int TRANSFER_PROGRESS_PENDING = 2;
public static final int TRANSFER_PROGRESS_FAILED = 3;
private static final String PART_ID_WHERE = ROW_ID + " = ? AND " + UNIQUE_ID + " = ?";
private static final String[] PROJECTION = new String[] {ROW_ID,
MMS_ID, CONTENT_TYPE, NAME, CONTENT_DISPOSITION,
CONTENT_LOCATION, DATA, THUMBNAIL, TRANSFER_STATE,
SIZE, FILE_NAME, THUMBNAIL, THUMBNAIL_ASPECT_RATIO,
UNIQUE_ID, DIGEST, FAST_PREFLIGHT_ID, VOICE_NOTE,
QUOTE, DATA_RANDOM, THUMBNAIL_RANDOM, WIDTH, HEIGHT};
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ROW_ID + " INTEGER PRIMARY KEY, " +
MMS_ID + " INTEGER, " + "seq" + " INTEGER DEFAULT 0, " +
CONTENT_TYPE + " TEXT, " + NAME + " TEXT, " + "chset" + " INTEGER, " +
CONTENT_DISPOSITION + " TEXT, " + "fn" + " TEXT, " + "cid" + " TEXT, " +
CONTENT_LOCATION + " TEXT, " + "ctt_s" + " INTEGER, " +
"ctt_t" + " TEXT, " + "encrypted" + " INTEGER, " +
TRANSFER_STATE + " INTEGER, "+ DATA + " TEXT, " + SIZE + " INTEGER, " +
FILE_NAME + " TEXT, " + THUMBNAIL + " TEXT, " + THUMBNAIL_ASPECT_RATIO + " REAL, " +
UNIQUE_ID + " INTEGER NOT NULL, " + DIGEST + " BLOB, " + FAST_PREFLIGHT_ID + " TEXT, " +
VOICE_NOTE + " INTEGER DEFAULT 0, " + DATA_RANDOM + " BLOB, " + THUMBNAIL_RANDOM + " BLOB, " +
QUOTE + " INTEGER DEFAULT 0, " + WIDTH + " INTEGER DEFAULT 0, " + HEIGHT + " INTEGER DEFAULT 0);";
public static final String[] CREATE_INDEXS = {
"CREATE INDEX IF NOT EXISTS part_mms_id_index ON " + TABLE_NAME + " (" + MMS_ID + ");",
"CREATE INDEX IF NOT EXISTS pending_push_index ON " + TABLE_NAME + " (" + TRANSFER_STATE + ");",
};
private final ExecutorService thumbnailExecutor = Util.newSingleThreadedLifoExecutor();
private final AttachmentSecret attachmentSecret;
public AttachmentDatabase(Context context, SQLCipherOpenHelper databaseHelper, AttachmentSecret attachmentSecret) {
@@ -139,52 +92,6 @@ public class AttachmentDatabase extends Database {
else return dataStream;
}
public @NonNull InputStream getThumbnailStream(@NonNull AttachmentId attachmentId)
throws IOException
{
Log.w(TAG, "getThumbnailStream(" + attachmentId + ")");
InputStream dataStream = getDataStream(attachmentId, THUMBNAIL, 0);
if (dataStream != null) {
return dataStream;
}
try {
InputStream generatedStream = thumbnailExecutor.submit(new ThumbnailFetchCallable(attachmentId)).get();
if (generatedStream == null) throw new FileNotFoundException("No thumbnail stream available: " + attachmentId);
else return generatedStream;
} catch (InterruptedException ie) {
throw new AssertionError("interrupted");
} catch (ExecutionException ee) {
Log.w(TAG, ee);
throw new IOException(ee);
}
}
public @Nullable DatabaseAttachment getAttachment(@NonNull AttachmentId attachmentId)
{
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = null;
try {
cursor = database.query(TABLE_NAME, PROJECTION, PART_ID_WHERE, attachmentId.toStrings(), null, null, null);
if (cursor != null && cursor.moveToFirst()) {
List<DatabaseAttachment> list = getAttachment(cursor);
if (list != null && list.size() > 0) {
return list.get(0);
}
}
return null;
} finally {
if (cursor != null)
cursor.close();
}
}
@SuppressWarnings("WeakerAccess")
@VisibleForTesting
protected @Nullable InputStream getDataStream(AttachmentId attachmentId, String dataType, long offset)
@@ -250,31 +157,6 @@ public class AttachmentDatabase extends Database {
}
private @NonNull DataInfo setAttachmentData(@NonNull InputStream in)
throws MmsException
{
try {
File partsDirectory = context.getDir(DIRECTORY, Context.MODE_PRIVATE);
File dataFile = File.createTempFile("part", ".mms", partsDirectory);
return setAttachmentData(dataFile, in);
} catch (IOException e) {
throw new MmsException(e);
}
}
private @NonNull DataInfo setAttachmentData(@NonNull File destination, @NonNull InputStream in)
throws MmsException
{
try {
Pair<byte[], OutputStream> out = ModernEncryptingPartOutputStream.createFor(attachmentSecret, destination, false);
long length = Util.copy(in, out.second);
return new DataInfo(destination, length, out.first);
} catch (IOException e) {
throw new MmsException(e);
}
}
public List<DatabaseAttachment> getAttachment(@NonNull Cursor cursor) {
try {
if (cursor.getColumnIndex(AttachmentDatabase.ATTACHMENT_JSON_ALIAS) != -1) {
@@ -335,110 +217,12 @@ public class AttachmentDatabase extends Database {
}
}
@SuppressWarnings("WeakerAccess")
@VisibleForTesting
protected void updateAttachmentThumbnail(AttachmentId attachmentId, InputStream in, float aspectRatio)
throws MmsException
{
Log.w(TAG, "updating part thumbnail for #" + attachmentId);
DataInfo thumbnailFile = setAttachmentData(in);
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues values = new ContentValues(2);
values.put(THUMBNAIL, thumbnailFile.file.getAbsolutePath());
values.put(THUMBNAIL_ASPECT_RATIO, aspectRatio);
values.put(THUMBNAIL_RANDOM, thumbnailFile.random);
database.update(TABLE_NAME, values, PART_ID_WHERE, attachmentId.toStrings());
Cursor cursor = database.query(TABLE_NAME, new String[] {MMS_ID}, PART_ID_WHERE, attachmentId.toStrings(), null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
// notifyConversationListeners(
// DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(cursor.getLong(cursor.getColumnIndexOrThrow(MMS_ID))));
}
} finally {
if (cursor != null) cursor.close();
}
}
@VisibleForTesting
class ThumbnailFetchCallable implements Callable<InputStream> {
private final AttachmentId attachmentId;
ThumbnailFetchCallable(AttachmentId attachmentId) {
this.attachmentId = attachmentId;
}
@Override
public @Nullable InputStream call() throws Exception {
Log.w(TAG, "Executing thumbnail job...");
final InputStream stream = getDataStream(attachmentId, THUMBNAIL, 0);
if (stream != null) {
return stream;
}
DatabaseAttachment attachment = getAttachment(attachmentId);
if (attachment == null || !attachment.hasData()) {
return null;
}
ThumbnailData data = null;
if (MediaUtil.isVideoType(attachment.getContentType())) {
data = generateVideoThumbnail(attachmentId);
}
if (data == null) {
return null;
}
updateAttachmentThumbnail(attachmentId, data.toDataStream(), data.getAspectRatio());
return getDataStream(attachmentId, THUMBNAIL, 0);
}
@SuppressLint("NewApi")
private ThumbnailData generateVideoThumbnail(AttachmentId attachmentId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Log.w(TAG, "Video thumbnails not supported...");
return null;
}
DataInfo dataInfo = getAttachmentDataFileInfo(attachmentId, DATA);
if (dataInfo == null) {
Log.w(TAG, "No data file found for video thumbnail...");
return null;
}
EncryptedMediaDataSource dataSource = new EncryptedMediaDataSource(attachmentSecret, dataInfo.file, dataInfo.random, dataInfo.length);
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(dataSource);
Bitmap bitmap = retriever.getFrameAtTime(1000);
Log.w(TAG, "Generated video thumbnail...");
return new ThumbnailData(bitmap);
}
}
private static class DataInfo {
private final File file;
private final long length;
private final byte[] random;
private DataInfo(File file, long length, byte[] random) {
this.file = file;
this.length = length;
this.random = random;
}
}
@@ -1,8 +1,6 @@
package org.thoughtcrime.securesms.database;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.support.annotation.NonNull;
import java.io.Closeable;
@@ -31,15 +29,6 @@ public class CursorList<T> implements List<T>, Closeable {
this.modelBuilder = modelBuilder;
}
public static <T> CursorList<T> emptyList() {
//noinspection ConstantConditions,unchecked
return (CursorList<T>) new CursorList(emptyCursor(), null);
}
private static Cursor emptyCursor() {
return new MatrixCursor(new String[] { "a" }, 0);
}
@Override
public int size() {
return cursor.getCount();
@@ -186,14 +175,6 @@ public class CursorList<T> implements List<T>, Closeable {
}
}
public void registerContentObserver(@NonNull ContentObserver observer) {
cursor.registerContentObserver(observer);
}
public void unregisterContentObserver(@NonNull ContentObserver observer) {
cursor.unregisterContentObserver(observer);
}
public interface ModelBuilder<T> {
T build(@NonNull Cursor cursor);
}
@@ -67,14 +67,6 @@ public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHold
return cursor;
}
public void setHeaderView(@Nullable View header) {
this.header = header;
}
public void setFooterView(@Nullable View footer) {
this.footer = footer;
}
public boolean hasHeaderView() {
return header != null;
}
@@ -17,22 +17,14 @@
package org.thoughtcrime.securesms.database;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import java.util.Set;
public abstract class Database {
protected static final String ID_WHERE = "_id = ?";
private static final String CONVERSATION_URI = "content://textsecure/thread/";
private static final String CONVERSATION_LIST_URI = "content://textsecure/conversation-list";
private static final String ATTACHMENT_URI = "content://textsecure/attachment/";
protected SQLCipherOpenHelper databaseHelper;
protected final Context context;
@@ -41,22 +33,10 @@ public abstract class Database {
this.databaseHelper = databaseHelper;
}
protected void notifyConversationListeners(long threadId) {
context.getContentResolver().notifyChange(Uri.parse(CONVERSATION_URI + threadId), null);
}
protected void notifyConversationListListeners() {
context.getContentResolver().notifyChange(Uri.parse(CONVERSATION_LIST_URI), null);
}
protected void setNotifyConverationListeners(Cursor cursor, long threadId) {
cursor.setNotificationUri(context.getContentResolver(), Uri.parse(CONVERSATION_URI + threadId));
}
protected void setNotifyConverationListListeners(Cursor cursor) {
cursor.setNotificationUri(context.getContentResolver(), Uri.parse(CONVERSATION_LIST_URI));
}
public void reset(SQLCipherOpenHelper databaseHelper) {
this.databaseHelper = databaseHelper;
}
@@ -5,8 +5,6 @@ import android.database.Cursor;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import net.sqlcipher.database.SQLiteDatabase;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
@@ -14,29 +12,10 @@ import java.util.List;
public class MediaDatabase extends Database {
private static final String BASE_MEDIA_QUERY = null;
private static final String GALLERY_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, AttachmentDatabase.CONTENT_TYPE + " LIKE 'image/%' OR " + AttachmentDatabase.CONTENT_TYPE + " LIKE 'video/%'");
private static final String DOCUMENT_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, AttachmentDatabase.CONTENT_TYPE + " NOT LIKE 'image/%' AND " + AttachmentDatabase.CONTENT_TYPE + " NOT LIKE 'video/%' AND " + AttachmentDatabase.CONTENT_TYPE + " NOT LIKE 'audio/%'");
MediaDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
super(context, databaseHelper);
}
public Cursor getGalleryMediaForThread(long threadId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = database.rawQuery(GALLERY_MEDIA_QUERY, new String[]{threadId+""});
setNotifyConverationListeners(cursor, threadId);
return cursor;
}
public Cursor getDocumentMediaForThread(long threadId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = database.rawQuery(DOCUMENT_MEDIA_QUERY, new String[]{threadId+""});
setNotifyConverationListeners(cursor, threadId);
return cursor;
}
public static class MediaRecord {
private final DatabaseAttachment attachment;
@@ -1,15 +0,0 @@
package org.thoughtcrime.securesms.database;
import android.content.Context;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
public abstract class MessagingDatabase extends Database implements MmsSmsColumns {
private static final String TAG = MessagingDatabase.class.getSimpleName();
public MessagingDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
super(context, databaseHelper);
}
}
@@ -4,30 +4,14 @@ package org.thoughtcrime.securesms.database;
public interface MmsSmsColumns {
public static final String ID = "_id";
public static final String NORMALIZED_DATE_SENT = "date_sent";
public static final String NORMALIZED_DATE_RECEIVED = "date_received";
public static final String THREAD_ID = "thread_id";
public static final String READ = "read";
public static final String BODY = "body";
public static final String ADDRESS = "address";
public static final String ADDRESS_DEVICE_ID = "address_device_id";
public static final String DELIVERY_RECEIPT_COUNT = "delivery_receipt_count";
public static final String READ_RECEIPT_COUNT = "read_receipt_count";
public static final String MISMATCHED_IDENTITIES = "mismatched_identities";
public static final String UNIQUE_ROW_ID = "unique_row_id";
public static final String SUBSCRIPTION_ID = "subscription_id";
public static final String EXPIRES_IN = "expires_in";
public static final String EXPIRE_STARTED = "expire_started";
public static final String NOTIFIED = "notified";
public static class Types {
// Base Types
protected static final long BASE_TYPE_MASK = 0x1F;
protected static final long INCOMING_CALL_TYPE = 1;
protected static final long OUTGOING_CALL_TYPE = 2;
protected static final long MISSED_CALL_TYPE = 3;
protected static final long JOINED_TYPE = 4;
protected static final long BASE_OUTBOX_TYPE = 21;
protected static final long BASE_SENDING_TYPE = 22;
@@ -42,36 +26,17 @@ public interface MmsSmsColumns {
BASE_PENDING_INSECURE_SMS_FALLBACK,
OUTGOING_CALL_TYPE};
// Message attributes
protected static final long MESSAGE_FORCE_SMS_BIT = 0x40;
// Key Exchange Information
protected static final long KEY_EXCHANGE_BIT = 0x8000;
protected static final long KEY_EXCHANGE_IDENTITY_VERIFIED_BIT = 0x4000;
protected static final long KEY_EXCHANGE_IDENTITY_DEFAULT_BIT = 0x2000;
protected static final long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000;
protected static final long KEY_EXCHANGE_INVALID_VERSION_BIT = 0x800;
protected static final long KEY_EXCHANGE_BUNDLE_BIT = 0x400;
protected static final long KEY_EXCHANGE_IDENTITY_UPDATE_BIT = 0x200;
protected static final long KEY_EXCHANGE_CONTENT_FORMAT = 0x100;
// Secure Message Information
protected static final long SECURE_MESSAGE_BIT = 0x800000;
protected static final long END_SESSION_BIT = 0x400000;
protected static final long PUSH_MESSAGE_BIT = 0x200000;
// Group Message Information
protected static final long GROUP_UPDATE_BIT = 0x10000;
protected static final long GROUP_QUIT_BIT = 0x20000;
protected static final long EXPIRATION_TIMER_UPDATE_BIT = 0x40000;
// Encrypted Storage Information XXX
// public static final long ENCRYPTION_SYMMETRIC_BIT = 0x80000000; Deprecated
// protected static final long ENCRYPTION_ASYMMETRIC_BIT = 0x40000000; Deprecated
protected static final long ENCRYPTION_REMOTE_BIT = 0x20000000;
protected static final long ENCRYPTION_REMOTE_FAILED_BIT = 0x10000000;
protected static final long ENCRYPTION_REMOTE_NO_SESSION_BIT = 0x08000000;
protected static final long ENCRYPTION_REMOTE_DUPLICATE_BIT = 0x04000000;
protected static final long ENCRYPTION_REMOTE_LEGACY_BIT = 0x02000000;
public static boolean isFailedMessageType(long type) {
@@ -87,10 +52,6 @@ public interface MmsSmsColumns {
return false;
}
public static boolean isForcedSms(long type) {
return (type & MESSAGE_FORCE_SMS_BIT) != 0;
}
public static boolean isPendingMessageType(long type) {
return
(type & BASE_TYPE_MASK) == BASE_OUTBOX_TYPE ||
@@ -101,26 +62,10 @@ public interface MmsSmsColumns {
return (type & BASE_TYPE_MASK) == BASE_PENDING_SECURE_SMS_FALLBACK;
}
public static boolean isJoinedType(long type) {
return (type & BASE_TYPE_MASK) == JOINED_TYPE;
}
public static boolean isSecureType(long type) {
return (type & SECURE_MESSAGE_BIT) != 0;
}
public static boolean isPushType(long type) {
return (type & PUSH_MESSAGE_BIT) != 0;
}
public static boolean isEndSessionType(long type) {
return (type & END_SESSION_BIT) != 0;
}
public static boolean isKeyExchangeType(long type) {
return (type & KEY_EXCHANGE_BIT) != 0;
}
public static boolean isIdentityVerified(long type) {
return (type & KEY_EXCHANGE_IDENTITY_VERIFIED_BIT) != 0;
}
@@ -129,66 +74,6 @@ public interface MmsSmsColumns {
return (type & KEY_EXCHANGE_IDENTITY_DEFAULT_BIT) != 0;
}
public static boolean isCorruptedKeyExchange(long type) {
return (type & KEY_EXCHANGE_CORRUPTED_BIT) != 0;
}
public static boolean isInvalidVersionKeyExchange(long type) {
return (type & KEY_EXCHANGE_INVALID_VERSION_BIT) != 0;
}
public static boolean isBundleKeyExchange(long type) {
return (type & KEY_EXCHANGE_BUNDLE_BIT) != 0;
}
public static boolean isContentBundleKeyExchange(long type) {
return (type & KEY_EXCHANGE_CONTENT_FORMAT) != 0;
}
public static boolean isIdentityUpdate(long type) {
return (type & KEY_EXCHANGE_IDENTITY_UPDATE_BIT) != 0;
}
public static boolean isCallLog(long type) {
return type == INCOMING_CALL_TYPE || type == OUTGOING_CALL_TYPE || type == MISSED_CALL_TYPE;
}
public static boolean isExpirationTimerUpdate(long type) {
return (type & EXPIRATION_TIMER_UPDATE_BIT) != 0;
}
public static boolean isIncomingCall(long type) {
return type == INCOMING_CALL_TYPE;
}
public static boolean isOutgoingCall(long type) {
return type == OUTGOING_CALL_TYPE;
}
public static boolean isMissedCall(long type) {
return type == MISSED_CALL_TYPE;
}
public static boolean isGroupUpdate(long type) {
return (type & GROUP_UPDATE_BIT) != 0;
}
public static boolean isGroupQuit(long type) {
return (type & GROUP_QUIT_BIT) != 0;
}
public static boolean isFailedDecryptType(long type) {
return (type & ENCRYPTION_REMOTE_FAILED_BIT) != 0;
}
public static boolean isDuplicateMessageType(long type) {
return (type & ENCRYPTION_REMOTE_DUPLICATE_BIT) != 0;
}
public static boolean isNoRemoteSessionType(long type) {
return (type & ENCRYPTION_REMOTE_NO_SESSION_BIT) != 0;
}
public static boolean isLegacyType(long type) {
return (type & ENCRYPTION_REMOTE_LEGACY_BIT) != 0 ||
(type & ENCRYPTION_REMOTE_BIT) != 0;
@@ -1,36 +0,0 @@
package org.thoughtcrime.securesms.database.documents;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.thoughtcrime.securesms.database.Address;
public class NetworkFailure {
@JsonProperty(value = "a")
private String address;
public NetworkFailure(Address address) {
this.address = address.serialize();
}
public NetworkFailure() {}
@JsonIgnore
public Address getAddress() {
return Address.fromSerialized(address);
}
@Override
public boolean equals(Object other) {
if (other == null || !(other instanceof NetworkFailure)) return false;
NetworkFailure that = (NetworkFailure)other;
return this.address.equals(that.address);
}
@Override
public int hashCode() {
return address.hashCode();
}
}
@@ -1,33 +0,0 @@
package org.thoughtcrime.securesms.database.documents;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.LinkedList;
import java.util.List;
public class NetworkFailureList implements Document<NetworkFailure> {
@JsonProperty(value = "l")
private List<NetworkFailure> failures;
public NetworkFailureList() {
this.failures = new LinkedList<>();
}
public NetworkFailureList(List<NetworkFailure> failures) {
this.failures = failures;
}
@Override
public int size() {
if (failures == null) return 0;
else return failures.size();
}
@Override
@JsonIgnore
public List<NetworkFailure> getList() {
return failures;
}
}
@@ -11,12 +11,10 @@ import org.thoughtcrime.securesms.util.AbstractCursorLoader;
public class ThreadMediaLoader extends AbstractCursorLoader {
private final Address address;
private final boolean gallery;
public ThreadMediaLoader(@NonNull Context context, @NonNull Address address, boolean gallery) {
super(context);
this.address = address;
this.gallery = gallery;
}
@Override
@@ -41,9 +41,6 @@ public abstract class DisplayRecord {
private final long dateReceived;
private final long threadId;
private final String body;
private final int deliveryStatus;
private final int deliveryReceiptCount;
private final int readReceiptCount;
DisplayRecord(Context context, String body, Recipient recipient, long dateSent,
long dateReceived, long threadId, int deliveryStatus, int deliveryReceiptCount,
@@ -56,9 +53,6 @@ public abstract class DisplayRecord {
this.dateReceived = dateReceived;
this.type = type;
this.body = body;
this.deliveryReceiptCount = deliveryReceiptCount;
this.readReceiptCount = readReceiptCount;
this.deliveryStatus = deliveryStatus;
}
public @NonNull String getBody() {
@@ -102,10 +96,6 @@ public abstract class DisplayRecord {
return threadId;
}
public boolean isKeyExchange() {
return false;
}
public boolean isEndSession() {
return false;
}
@@ -1,83 +0,0 @@
/**
* Copyright (C) 2012 Moxie Marlinspike
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.SpannableString;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient;
import java.util.List;
/**
* Represents the message record model for MMS messages that contain
* media (ie: they've been downloaded).
*
* @author Moxie Marlinspike
*
*/
public class MediaMmsMessageRecord extends MmsMessageRecord {
private final static String TAG = MediaMmsMessageRecord.class.getSimpleName();
private final Context context;
private final int partCount;
public MediaMmsMessageRecord(Context context, long id, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId,
long dateSent, long dateReceived, int deliveryReceiptCount,
long threadId, String body,
@NonNull SlideDeck slideDeck,
int partCount, long mailbox,
List<IdentityKeyMismatch> mismatches,
List<NetworkFailure> failures, int subscriptionId,
long expiresIn, long expireStarted, int readReceiptCount,
@Nullable Quote quote, @Nullable List<Contact> contacts)
{
super(context, id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent,
dateReceived, threadId, 0, deliveryReceiptCount, mailbox, mismatches, failures,
subscriptionId, expiresIn, expireStarted, slideDeck, readReceiptCount, quote, contacts);
this.context = context.getApplicationContext();
this.partCount = partCount;
}
public int getPartCount() {
return partCount;
}
@Override
public boolean isMmsNotification() {
return false;
}
@Override
public SpannableString getDisplayBody() {
if (isLegacyMessage()) {
return emphasisAdded(context.getString(R.string.MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported));
}
return super.getDisplayBody();
}
}
@@ -17,20 +17,13 @@
package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import java.util.List;
/**
* The base class for message record models that are displayed in
* conversations, as opposed to models that are displayed in a thread list.
@@ -44,10 +37,7 @@ public abstract class MessageRecord extends DisplayRecord {
private static final int MAX_DISPLAY_LENGTH = 2000;
private final Recipient individualRecipient;
private final int recipientDeviceId;
private final long id;
private final List<IdentityKeyMismatch> mismatches;
private final List<NetworkFailure> networkFailures;
private final int subscriptionId;
private final long expiresIn;
private final long expireStarted;
@@ -56,8 +46,6 @@ public abstract class MessageRecord extends DisplayRecord {
Recipient individualRecipient, int recipientDeviceId,
long dateSent, long dateReceived, long threadId,
int deliveryStatus, int deliveryReceiptCount, long type,
List<IdentityKeyMismatch> mismatches,
List<NetworkFailure> networkFailures,
int subscriptionId, long expiresIn, long expireStarted,
int readReceiptCount)
{
@@ -65,25 +53,17 @@ public abstract class MessageRecord extends DisplayRecord {
threadId, deliveryStatus, deliveryReceiptCount, type, readReceiptCount);
this.id = id;
this.individualRecipient = individualRecipient;
this.recipientDeviceId = recipientDeviceId;
this.mismatches = mismatches;
this.networkFailures = networkFailures;
this.subscriptionId = subscriptionId;
this.expiresIn = expiresIn;
this.expireStarted = expireStarted;
}
public abstract boolean isMms();
public abstract boolean isMmsNotification();
public boolean isSecure() {
return MmsSmsColumns.Types.isSecureType(type);
}
public boolean isLegacyMessage() {
return MmsSmsColumns.Types.isLegacyType(type);
}
@Override
public SpannableString getDisplayBody() {
if (isGroupUpdate() && isOutgoing()) {
@@ -147,51 +127,23 @@ public abstract class MessageRecord extends DisplayRecord {
return false;
}
public boolean isBundleKeyExchange() {
return false;
}
public boolean isIdentityUpdate() {
return false;
}
public boolean isCorruptedKeyExchange() {
return false;
}
public boolean isInvalidVersionKeyExchange() {
return false;
}
public boolean isUpdate() {
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault();
}
public boolean isMediaPending() {
return false;
}
public Recipient getIndividualRecipient() {
return individualRecipient;
}
public int getRecipientDeviceId() {
return recipientDeviceId;
}
public long getType() {
return type;
}
protected SpannableString emphasisAdded(String sequence) {
SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new RelativeSizeSpan(0.9f), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
}
public boolean equals(Object other) {
return other != null &&
other instanceof MessageRecord &&
@@ -203,15 +155,7 @@ public abstract class MessageRecord extends DisplayRecord {
return (int)getId();
}
public int getSubscriptionId() {
return subscriptionId;
}
public long getExpiresIn() {
return expiresIn;
}
public long getExpireStarted() {
return expireStarted;
}
}
@@ -1,72 +0,0 @@
package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient;
import java.util.LinkedList;
import java.util.List;
public abstract class MmsMessageRecord extends MessageRecord {
private final @NonNull SlideDeck slideDeck;
private final @Nullable Quote quote;
private final @NonNull List<Contact> contacts = new LinkedList<>();
MmsMessageRecord(Context context, long id, String body, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId, long dateSent,
long dateReceived, long threadId, int deliveryStatus, int deliveryReceiptCount,
long type, List<IdentityKeyMismatch> mismatches,
List<NetworkFailure> networkFailures, int subscriptionId, long expiresIn,
long expireStarted, @NonNull SlideDeck slideDeck, int readReceiptCount,
@Nullable Quote quote, @NonNull List<Contact> contacts)
{
super(context, id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent, dateReceived, threadId, deliveryStatus, deliveryReceiptCount, type, mismatches, networkFailures, subscriptionId, expiresIn, expireStarted, readReceiptCount);
this.slideDeck = slideDeck;
this.quote = quote;
this.contacts.addAll(contacts);
}
@Override
public boolean isMms() {
return true;
}
@NonNull
public SlideDeck getSlideDeck() {
return slideDeck;
}
@Override
public boolean isMediaPending() {
for (Slide slide : getSlideDeck().getSlides()) {
if (slide.isInProgress() || slide.isPendingDownload()) {
return true;
}
}
return false;
}
public boolean containsMediaSlide() {
return slideDeck.containsMediaSlide();
}
public @Nullable Quote getQuote() {
return quote;
}
public @NonNull List<Contact> getSharedContacts() {
return contacts;
}
}
@@ -1,115 +0,0 @@
/*
* Copyright (C) 2012 Moxie Marlinspike
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.text.SpannableString;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient;
import java.util.Collections;
import java.util.LinkedList;
/**
* Represents the message record model for MMS messages that are
* notifications (ie: they're pointers to undownloaded media).
*
* @author Moxie Marlinspike
*
*/
public class NotificationMmsMessageRecord extends MmsMessageRecord {
private final byte[] contentLocation;
private final long messageSize;
private final long expiry;
private final int status;
private final byte[] transactionId;
public NotificationMmsMessageRecord(Context context, long id, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId,
long dateSent, long dateReceived, int deliveryReceiptCount,
long threadId, byte[] contentLocation, long messageSize,
long expiry, int status, byte[] transactionId, long mailbox,
int subscriptionId, SlideDeck slideDeck, int readReceiptCount)
{
super(context, id, "", conversationRecipient, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, 0, deliveryReceiptCount, mailbox,
new LinkedList<IdentityKeyMismatch>(), new LinkedList<NetworkFailure>(), subscriptionId,
0, 0, slideDeck, readReceiptCount, null, Collections.emptyList());
this.contentLocation = contentLocation;
this.messageSize = messageSize;
this.expiry = expiry;
this.status = status;
this.transactionId = transactionId;
}
public byte[] getTransactionId() {
return transactionId;
}
public int getStatus() {
return this.status;
}
public byte[] getContentLocation() {
return contentLocation;
}
public long getMessageSize() {
return (messageSize + 1023) / 1024;
}
public long getExpiration() {
return expiry * 1000;
}
@Override
public boolean isOutgoing() {
return false;
}
@Override
public boolean isSecure() {
return false;
}
@Override
public boolean isPending() {
return false;
}
@Override
public boolean isMmsNotification() {
return true;
}
@Override
public boolean isMediaPending() {
return true;
}
@Override
public SpannableString getDisplayBody() {
return emphasisAdded(context.getString(R.string.NotificationMmsMessageRecord_error_downloading_mms_message));
}
}
@@ -1,39 +0,0 @@
package org.thoughtcrime.securesms.database.model;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.mms.SlideDeck;
public class Quote {
private final long id;
private final Address author;
private final String text;
private final SlideDeck attachment;
public Quote(long id, @NonNull Address author, @Nullable String text, @NonNull SlideDeck attachment) {
this.id = id;
this.author = author;
this.text = text;
this.attachment = attachment;
}
public long getId() {
return id;
}
public @NonNull Address getAuthor() {
return author;
}
public @Nullable String getText() {
return text;
}
public @NonNull SlideDeck getAttachment() {
return attachment;
}
}
@@ -1,93 +0,0 @@
/*
* Copyright (C) 2012 Moxie Marlinspike
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.text.SpannableString;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.recipients.Recipient;
import java.util.LinkedList;
import java.util.List;
/**
* The message record model which represents standard SMS messages.
*
* @author Moxie Marlinspike
*
*/
public class SmsMessageRecord extends MessageRecord {
public SmsMessageRecord(Context context, long id,
String body, Recipient recipient,
Recipient individualRecipient,
int recipientDeviceId,
long dateSent, long dateReceived,
int deliveryReceiptCount,
long type, long threadId,
int status, List<IdentityKeyMismatch> mismatches,
int subscriptionId, long expiresIn, long expireStarted,
int readReceiptCount)
{
super(context, id, body, recipient, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, status, deliveryReceiptCount, type,
mismatches, new LinkedList<>(), subscriptionId,
expiresIn, expireStarted, readReceiptCount);
}
public long getType() {
return type;
}
@Override
public SpannableString getDisplayBody() {
if (isCorruptedKeyExchange()) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_corrupted_key_exchange_message));
} else if (isInvalidVersionKeyExchange()) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_key_exchange_message_for_invalid_protocol_version));
} else if (MmsSmsColumns.Types.isLegacyType(type)) {
return emphasisAdded(context.getString(R.string.MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported));
} else if (isBundleKeyExchange()) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_message_with_new_safety_number_tap_to_process));
} else if (isKeyExchange() && isOutgoing()) {
return new SpannableString("");
} else if (isKeyExchange() && !isOutgoing()) {
return emphasisAdded(context.getString(R.string.ConversationItem_received_key_exchange_message_tap_to_process));
} else if (isEndSession() && isOutgoing()) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset));
} else if (isEndSession()) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset_s, getIndividualRecipient().toShortString()));
} else {
return super.getDisplayBody();
}
}
@Override
public boolean isMms() {
return false;
}
@Override
public boolean isMmsNotification() {
return false;
}
}