Support for attachment digests

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2017-02-26 10:06:27 -08:00
parent a37d2f568c
commit 79e925051a
15 changed files with 89 additions and 33 deletions

View File

@ -57,7 +57,7 @@ dependencies {
compile 'org.whispersystems:jobmanager:1.0.2' compile 'org.whispersystems:jobmanager:1.0.2'
compile 'org.whispersystems:libpastelog:1.0.7' compile 'org.whispersystems:libpastelog:1.0.7'
compile 'org.whispersystems:signal-service-android:2.5.1' compile 'org.whispersystems:signal-service-android:2.5.2'
compile 'org.whispersystems:webrtc-android:M57' compile 'org.whispersystems:webrtc-android:M57'
compile "me.leolin:ShortcutBadger:1.10-WS1" compile "me.leolin:ShortcutBadger:1.10-WS1"
@ -127,7 +127,7 @@ dependencyVerification {
'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b', 'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b',
'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181', 'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181',
'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88', 'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88',
'org.whispersystems:signal-service-android:b0329b155cc9ad5e7fc08e4660538df1827c6d9485b05cab41946f36ad7ee0ab', 'org.whispersystems:signal-service-android:030294f4f1517f032892f8100e649ac2ee6db39cf5cfaf42b00cc22ccd66b14b',
'org.whispersystems:webrtc-android:acf78f6148c2e946b846cc5395887079ba37ddb892bf0d993fed18f1b9f521f8', 'org.whispersystems:webrtc-android:acf78f6148c2e946b846cc5395887079ba37ddb892bf0d993fed18f1b9f521f8',
'me.leolin:ShortcutBadger:e8e39df8a59d8211a30f40b1eeab21b3fa57b3f3e0f03abb995f82d66588778c', 'me.leolin:ShortcutBadger:e8e39df8a59d8211a30f40b1eeab21b3fa57b3f3e0f03abb995f82d66588778c',
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb', 'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
@ -162,22 +162,22 @@ dependencyVerification {
'com.google.android.gms:play-services-base:0ca636a8fc9a5af45e607cdcd61783bf5d561cbbb0f862021ce69606eee5ad49', 'com.google.android.gms:play-services-base:0ca636a8fc9a5af45e607cdcd61783bf5d561cbbb0f862021ce69606eee5ad49',
'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d', 'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d',
'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70', 'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70',
'org.whispersystems:signal-service-java:e0b9c41fcf614d58a71afcbb290d1864275b65364ca8fafeb5fbcbdc2d59a57a',
'org.whispersystems:signal-protocol-android:1b4b9d557c8eaf861797ff683990d482d4aa8e9f23d9b17ff0cc67a02f38cb19', 'org.whispersystems:signal-protocol-android:1b4b9d557c8eaf861797ff683990d482d4aa8e9f23d9b17ff0cc67a02f38cb19',
'org.whispersystems:signal-service-java:49664fb9aedb6c39b303d20d167fa61bc25dc8d8bb148713ac29783383da1e90',
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a', 'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'com.google.android.gms:play-services-tasks:69ec265168e601d0203d04cd42e34bb019b2f029aa1e16fabd38a5153eea2086', 'com.google.android.gms:play-services-tasks:69ec265168e601d0203d04cd42e34bb019b2f029aa1e16fabd38a5153eea2086',
'org.whispersystems:curve25519-android:bf6c34223d45d2f2813a8efcab9923caf99115115c760c9acea680bcb42d23c0',
'org.whispersystems:signal-protocol-java:a835cd0609cf116a74651bd0aa748db9392bba48c2d2af787757b8a1b50d131c',
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74', 'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
'com.googlecode.libphonenumber:libphonenumber:141ebcafba7070a13d879c44e7648ddbe10beab665cb64d7b0c1bea93afb8dc2', 'com.googlecode.libphonenumber:libphonenumber:141ebcafba7070a13d879c44e7648ddbe10beab665cb64d7b0c1bea93afb8dc2',
'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d', 'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d',
'com.squareup.okhttp3:okhttp:a992938d7203ca557cd7a116f002e8c427ec9cdae7ea852441abb8aec891f948', 'com.squareup.okhttp3:okhttp:a992938d7203ca557cd7a116f002e8c427ec9cdae7ea852441abb8aec891f948',
'org.whispersystems:curve25519-android:bf6c34223d45d2f2813a8efcab9923caf99115115c760c9acea680bcb42d23c0', 'org.whispersystems:curve25519-java:00f1d4919f759055f41f7853a3d475dc7c8decf0dbf045ae93414f8f23b066cc',
'org.whispersystems:signal-protocol-java:a835cd0609cf116a74651bd0aa748db9392bba48c2d2af787757b8a1b50d131c',
'com.fasterxml.jackson.core:jackson-annotations:0ca408c24202a7626ec8b861e99d85eca5e38b73311dd6dd12e3e9deecc3fe94', 'com.fasterxml.jackson.core:jackson-annotations:0ca408c24202a7626ec8b861e99d85eca5e38b73311dd6dd12e3e9deecc3fe94',
'com.fasterxml.jackson.core:jackson-core:cbf4604784b4de226262845447a1ad3bb38a6728cebe86562e2c5afada8be2c0', 'com.fasterxml.jackson.core:jackson-core:cbf4604784b4de226262845447a1ad3bb38a6728cebe86562e2c5afada8be2c0',
'com.squareup.okio:okio:8c5436cadfab36bbd97db5f5c43b7bfdb5bf2f5f894ec8709b1929f14bdd010c', 'com.squareup.okio:okio:8c5436cadfab36bbd97db5f5c43b7bfdb5bf2f5f894ec8709b1929f14bdd010c',
'org.whispersystems:curve25519-java:00f1d4919f759055f41f7853a3d475dc7c8decf0dbf045ae93414f8f23b066cc',
'com.android.support:support-media-compat:8d6a1a5ba3d9eb1a25cb8f21bb312ac6280202e3d2900cb0b447d065d0d8a125', 'com.android.support:support-media-compat:8d6a1a5ba3d9eb1a25cb8f21bb312ac6280202e3d2900cb0b447d065d0d8a125',
'com.android.support:support-core-utils:a7649e18c04143dde40c218c5ce9a030e7ae674089cd7b18c6cf8ed2a22cf01a', 'com.android.support:support-core-utils:a7649e18c04143dde40c218c5ce9a030e7ae674089cd7b18c6cf8ed2a22cf01a',
'com.android.support:support-fragment:1294500b357f52cf3779e2521c79f54ae7844f3b9a5f6727495dbbda7f231377', 'com.android.support:support-fragment:1294500b357f52cf3779e2521c79f54ae7844f3b9a5f6727495dbbda7f231377',

View File

@ -22,8 +22,12 @@ public abstract class Attachment {
@Nullable @Nullable
private final String relay; private final String relay;
@Nullable
private final byte[] digest;
public Attachment(@NonNull String contentType, int transferState, long size, public Attachment(@NonNull String contentType, int transferState, long size,
@Nullable String location, @Nullable String key, @Nullable String relay) @Nullable String location, @Nullable String key, @Nullable String relay,
@Nullable byte[] digest)
{ {
this.contentType = contentType; this.contentType = contentType;
this.transferState = transferState; this.transferState = transferState;
@ -31,6 +35,7 @@ public abstract class Attachment {
this.location = location; this.location = location;
this.key = key; this.key = key;
this.relay = relay; this.relay = relay;
this.digest = digest;
} }
@Nullable @Nullable
@ -71,4 +76,9 @@ public abstract class Attachment {
public String getRelay() { public String getRelay() {
return relay; return relay;
} }
@Nullable
public byte[] getDigest() {
return digest;
}
} }

View File

@ -15,9 +15,9 @@ public class DatabaseAttachment extends Attachment {
public DatabaseAttachment(AttachmentId attachmentId, long mmsId, public DatabaseAttachment(AttachmentId attachmentId, long mmsId,
boolean hasData, boolean hasThumbnail, boolean hasData, boolean hasThumbnail,
String contentType, int transferProgress, long size, String contentType, int transferProgress, long size,
String location, String key, String relay) String location, String key, String relay, byte[] digest)
{ {
super(contentType, transferProgress, size, location, key, relay); super(contentType, transferProgress, size, location, key, relay, digest);
this.attachmentId = attachmentId; this.attachmentId = attachmentId;
this.hasData = hasData; this.hasData = hasData;
this.hasThumbnail = hasThumbnail; this.hasThumbnail = hasThumbnail;

View File

@ -10,7 +10,7 @@ import org.thoughtcrime.securesms.database.MmsDatabase;
public class MmsNotificationAttachment extends Attachment { public class MmsNotificationAttachment extends Attachment {
public MmsNotificationAttachment(int status, long size) { public MmsNotificationAttachment(int status, long size) {
super("application/mms", getTransferStateFromStatus(status), size, null, null, null); super("application/mms", getTransferStateFromStatus(status), size, null, null, null, null);
} }
@Nullable @Nullable

View File

@ -16,9 +16,10 @@ import java.util.List;
public class PointerAttachment extends Attachment { public class PointerAttachment extends Attachment {
public PointerAttachment(@NonNull String contentType, int transferState, long size, public PointerAttachment(@NonNull String contentType, int transferState, long size,
@NonNull String location, @NonNull String key, @NonNull String relay) @NonNull String location, @NonNull String key, @NonNull String relay,
@Nullable byte[] digest)
{ {
super(contentType, transferState, size, location, key, relay); super(contentType, transferState, size, location, key, relay, digest);
} }
@Nullable @Nullable
@ -45,7 +46,8 @@ public class PointerAttachment extends Attachment {
AttachmentDatabase.TRANSFER_PROGRESS_AUTO_PENDING, AttachmentDatabase.TRANSFER_PROGRESS_AUTO_PENDING,
pointer.asPointer().getSize().or(0), pointer.asPointer().getSize().or(0),
String.valueOf(pointer.asPointer().getId()), String.valueOf(pointer.asPointer().getId()),
encryptedKey, pointer.asPointer().getRelay().orNull())); encryptedKey, pointer.asPointer().getRelay().orNull(),
pointer.asPointer().getDigest().orNull()));
} }
} }
} }

View File

@ -16,7 +16,7 @@ public class UriAttachment extends Attachment {
public UriAttachment(@NonNull Uri dataUri, @Nullable Uri thumbnailUri, public UriAttachment(@NonNull Uri dataUri, @Nullable Uri thumbnailUri,
@NonNull String contentType, int transferState, long size) @NonNull String contentType, int transferState, long size)
{ {
super(contentType, transferState, size, null, null, null); super(contentType, transferState, size, null, null, null, null);
this.dataUri = dataUri; this.dataUri = dataUri;
this.thumbnailUri = thumbnailUri; this.thumbnailUri = thumbnailUri;
} }

View File

@ -79,6 +79,7 @@ public class AttachmentDatabase extends Database {
static final String THUMBNAIL = "thumbnail"; static final String THUMBNAIL = "thumbnail";
static final String THUMBNAIL_ASPECT_RATIO = "aspect_ratio"; static final String THUMBNAIL_ASPECT_RATIO = "aspect_ratio";
static final String UNIQUE_ID = "unique_id"; static final String UNIQUE_ID = "unique_id";
static final String DIGEST = "digest";
public static final int TRANSFER_PROGRESS_DONE = 0; public static final int TRANSFER_PROGRESS_DONE = 0;
public static final int TRANSFER_PROGRESS_STARTED = 1; public static final int TRANSFER_PROGRESS_STARTED = 1;
@ -91,7 +92,7 @@ public class AttachmentDatabase extends Database {
MMS_ID, CONTENT_TYPE, NAME, CONTENT_DISPOSITION, MMS_ID, CONTENT_TYPE, NAME, CONTENT_DISPOSITION,
CONTENT_LOCATION, DATA, THUMBNAIL, TRANSFER_STATE, CONTENT_LOCATION, DATA, THUMBNAIL, TRANSFER_STATE,
SIZE, THUMBNAIL, THUMBNAIL_ASPECT_RATIO, SIZE, THUMBNAIL, THUMBNAIL_ASPECT_RATIO,
UNIQUE_ID}; UNIQUE_ID, DIGEST};
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ROW_ID + " INTEGER PRIMARY KEY, " + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ROW_ID + " INTEGER PRIMARY KEY, " +
MMS_ID + " INTEGER, " + "seq" + " INTEGER DEFAULT 0, " + MMS_ID + " INTEGER, " + "seq" + " INTEGER DEFAULT 0, " +
@ -100,7 +101,8 @@ public class AttachmentDatabase extends Database {
CONTENT_LOCATION + " TEXT, " + "ctt_s" + " INTEGER, " + CONTENT_LOCATION + " TEXT, " + "ctt_s" + " INTEGER, " +
"ctt_t" + " TEXT, " + "encrypted" + " INTEGER, " + "ctt_t" + " TEXT, " + "encrypted" + " INTEGER, " +
TRANSFER_STATE + " INTEGER, "+ DATA + " TEXT, " + SIZE + " INTEGER, " + TRANSFER_STATE + " INTEGER, "+ DATA + " TEXT, " + SIZE + " INTEGER, " +
THUMBNAIL + " TEXT, " + THUMBNAIL_ASPECT_RATIO + " REAL, " + UNIQUE_ID + " INTEGER NOT NULL);"; THUMBNAIL + " TEXT, " + THUMBNAIL_ASPECT_RATIO + " REAL, " + UNIQUE_ID + " INTEGER NOT NULL, " +
DIGEST + " BLOB);";
public static final String[] CREATE_INDEXS = { 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 part_mms_id_index ON " + TABLE_NAME + " (" + MMS_ID + ");",
@ -266,6 +268,7 @@ public class AttachmentDatabase extends Database {
values.put(TRANSFER_STATE, TRANSFER_PROGRESS_DONE); values.put(TRANSFER_STATE, TRANSFER_PROGRESS_DONE);
values.put(CONTENT_LOCATION, (String)null); values.put(CONTENT_LOCATION, (String)null);
values.put(CONTENT_DISPOSITION, (String)null); values.put(CONTENT_DISPOSITION, (String)null);
values.put(DIGEST, (byte[])null);
values.put(NAME, (String) null); values.put(NAME, (String) null);
if (database.update(TABLE_NAME, values, PART_ID_WHERE, attachmentId.toStrings()) == 0) { if (database.update(TABLE_NAME, values, PART_ID_WHERE, attachmentId.toStrings()) == 0) {
@ -324,7 +327,8 @@ public class AttachmentDatabase extends Database {
dataSize, dataSize,
databaseAttachment.getLocation(), databaseAttachment.getLocation(),
databaseAttachment.getKey(), databaseAttachment.getKey(),
databaseAttachment.getRelay()); databaseAttachment.getRelay(),
databaseAttachment.getDigest());
} }
@ -446,7 +450,8 @@ public class AttachmentDatabase extends Database {
cursor.getLong(cursor.getColumnIndexOrThrow(SIZE)), cursor.getLong(cursor.getColumnIndexOrThrow(SIZE)),
cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_LOCATION)), cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_LOCATION)),
cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_DISPOSITION)), cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_DISPOSITION)),
cursor.getString(cursor.getColumnIndexOrThrow(NAME))); cursor.getString(cursor.getColumnIndexOrThrow(NAME)),
cursor.getBlob(cursor.getColumnIndexOrThrow(DIGEST)));
} }
@ -470,6 +475,7 @@ public class AttachmentDatabase extends Database {
contentValues.put(TRANSFER_STATE, attachment.getTransferState()); contentValues.put(TRANSFER_STATE, attachment.getTransferState());
contentValues.put(UNIQUE_ID, uniqueId); contentValues.put(UNIQUE_ID, uniqueId);
contentValues.put(CONTENT_LOCATION, attachment.getLocation()); contentValues.put(CONTENT_LOCATION, attachment.getLocation());
contentValues.put(DIGEST, attachment.getDigest());
contentValues.put(CONTENT_DISPOSITION, attachment.getKey()); contentValues.put(CONTENT_DISPOSITION, attachment.getKey());
contentValues.put(NAME, attachment.getRelay()); contentValues.put(NAME, attachment.getRelay());

View File

@ -74,7 +74,8 @@ public class DatabaseFactory {
private static final int INTRODUCED_SUBSCRIPTION_ID_VERSION = 27; private static final int INTRODUCED_SUBSCRIPTION_ID_VERSION = 27;
private static final int INTRODUCED_EXPIRE_MESSAGES_VERSION = 28; private static final int INTRODUCED_EXPIRE_MESSAGES_VERSION = 28;
private static final int INTRODUCED_LAST_SEEN = 29; private static final int INTRODUCED_LAST_SEEN = 29;
private static final int DATABASE_VERSION = 29; private static final int INTRODUCED_DIGEST = 30;
private static final int DATABASE_VERSION = 30;
private static final String DATABASE_NAME = "messages.db"; private static final String DATABASE_NAME = "messages.db";
private static final Object lock = new Object(); private static final Object lock = new Object();
@ -835,6 +836,11 @@ public class DatabaseFactory {
db.execSQL("ALTER TABLE thread ADD COLUMN last_seen INTEGER DEFAULT 0"); db.execSQL("ALTER TABLE thread ADD COLUMN last_seen INTEGER DEFAULT 0");
} }
if (oldVersion < INTRODUCED_DIGEST) {
db.execSQL("ALTER TABLE part ADD COLUMN digest BLOB");
db.execSQL("ALTER TABLE groups ADD COLUMN avatar_digest BLOB");
}
db.setTransactionSuccessful(); db.setTransactionSuccessful();
db.endTransaction(); db.endTransaction();
} }

View File

@ -43,6 +43,7 @@ public class GroupDatabase extends Database {
private static final String AVATAR_KEY = "avatar_key"; private static final String AVATAR_KEY = "avatar_key";
private static final String AVATAR_CONTENT_TYPE = "avatar_content_type"; private static final String AVATAR_CONTENT_TYPE = "avatar_content_type";
private static final String AVATAR_RELAY = "avatar_relay"; private static final String AVATAR_RELAY = "avatar_relay";
private static final String AVATAR_DIGEST = "avatar_digest";
private static final String TIMESTAMP = "timestamp"; private static final String TIMESTAMP = "timestamp";
private static final String ACTIVE = "active"; private static final String ACTIVE = "active";
@ -58,7 +59,8 @@ public class GroupDatabase extends Database {
AVATAR_CONTENT_TYPE + " TEXT, " + AVATAR_CONTENT_TYPE + " TEXT, " +
AVATAR_RELAY + " TEXT, " + AVATAR_RELAY + " TEXT, " +
TIMESTAMP + " INTEGER, " + TIMESTAMP + " INTEGER, " +
ACTIVE + " INTEGER DEFAULT 1);"; ACTIVE + " INTEGER DEFAULT 1, " +
AVATAR_DIGEST + " BLOB);";
public static final String[] CREATE_INDEXS = { public static final String[] CREATE_INDEXS = {
"CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON " + TABLE_NAME + " (" + GROUP_ID + ");", "CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON " + TABLE_NAME + " (" + GROUP_ID + ");",
@ -126,6 +128,7 @@ public class GroupDatabase extends Database {
contentValues.put(AVATAR_ID, avatar.getId()); contentValues.put(AVATAR_ID, avatar.getId());
contentValues.put(AVATAR_KEY, avatar.getKey()); contentValues.put(AVATAR_KEY, avatar.getKey());
contentValues.put(AVATAR_CONTENT_TYPE, avatar.getContentType()); contentValues.put(AVATAR_CONTENT_TYPE, avatar.getContentType());
contentValues.put(AVATAR_DIGEST, avatar.getDigest().orNull());
} }
contentValues.put(AVATAR_RELAY, relay); contentValues.put(AVATAR_RELAY, relay);
@ -144,6 +147,7 @@ public class GroupDatabase extends Database {
contentValues.put(AVATAR_ID, avatar.getId()); contentValues.put(AVATAR_ID, avatar.getId());
contentValues.put(AVATAR_CONTENT_TYPE, avatar.getContentType()); contentValues.put(AVATAR_CONTENT_TYPE, avatar.getContentType());
contentValues.put(AVATAR_KEY, avatar.getKey()); contentValues.put(AVATAR_KEY, avatar.getKey());
contentValues.put(AVATAR_DIGEST, avatar.getDigest().orNull());
} }
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues,
@ -269,7 +273,8 @@ public class GroupDatabase extends Database {
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_KEY)), cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_KEY)),
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_CONTENT_TYPE)), cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_CONTENT_TYPE)),
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_RELAY)), cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_RELAY)),
cursor.getInt(cursor.getColumnIndexOrThrow(ACTIVE)) == 1); cursor.getInt(cursor.getColumnIndexOrThrow(ACTIVE)) == 1,
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_DIGEST)));
} }
public void close() { public void close() {
@ -286,13 +291,14 @@ public class GroupDatabase extends Database {
private final byte[] avatar; private final byte[] avatar;
private final long avatarId; private final long avatarId;
private final byte[] avatarKey; private final byte[] avatarKey;
private final byte[] avatarDigest;
private final String avatarContentType; private final String avatarContentType;
private final String relay; private final String relay;
private final boolean active; private final boolean active;
public GroupRecord(String id, String title, String members, byte[] avatar, public GroupRecord(String id, String title, String members, byte[] avatar,
long avatarId, byte[] avatarKey, String avatarContentType, long avatarId, byte[] avatarKey, String avatarContentType,
String relay, boolean active) String relay, boolean active, byte[] avatarDigest)
{ {
this.id = id; this.id = id;
this.title = title; this.title = title;
@ -300,6 +306,7 @@ public class GroupDatabase extends Database {
this.avatar = avatar; this.avatar = avatar;
this.avatarId = avatarId; this.avatarId = avatarId;
this.avatarKey = avatarKey; this.avatarKey = avatarKey;
this.avatarDigest = avatarDigest;
this.avatarContentType = avatarContentType; this.avatarContentType = avatarContentType;
this.relay = relay; this.relay = relay;
this.active = active; this.active = active;
@ -337,6 +344,10 @@ public class GroupDatabase extends Database {
return avatarKey; return avatarKey;
} }
public byte[] getAvatarDigest() {
return avatarDigest;
}
public String getAvatarContentType() { public String getAvatarContentType() {
return avatarContentType; return avatarContentType;
} }

View File

@ -96,7 +96,7 @@ public class MediaDatabase extends Database {
} }
public Attachment getAttachment() { public Attachment getAttachment() {
return new DatabaseAttachment(attachmentId, mmsId, hasData, hasThumbnail, contentType, transferState, size, null, null, null); return new DatabaseAttachment(attachmentId, mmsId, hasData, hasThumbnail, contentType, transferState, size, null, null, null, null);
} }
public String getContentType() { public String getContentType() {

View File

@ -142,6 +142,7 @@ public class MmsDatabase extends MessagingDatabase {
AttachmentDatabase.THUMBNAIL, AttachmentDatabase.THUMBNAIL,
AttachmentDatabase.CONTENT_TYPE, AttachmentDatabase.CONTENT_TYPE,
AttachmentDatabase.CONTENT_LOCATION, AttachmentDatabase.CONTENT_LOCATION,
AttachmentDatabase.DIGEST,
AttachmentDatabase.CONTENT_DISPOSITION, AttachmentDatabase.CONTENT_DISPOSITION,
AttachmentDatabase.NAME, AttachmentDatabase.NAME,
AttachmentDatabase.TRANSFER_STATE AttachmentDatabase.TRANSFER_STATE
@ -681,7 +682,8 @@ public class MmsDatabase extends MessagingDatabase {
databaseAttachment.getSize(), databaseAttachment.getSize(),
databaseAttachment.getLocation(), databaseAttachment.getLocation(),
databaseAttachment.getKey(), databaseAttachment.getKey(),
databaseAttachment.getRelay())); databaseAttachment.getRelay(),
databaseAttachment.getDigest()));
} }
return insertMediaMessage(new MasterSecretUnion(masterSecret), return insertMediaMessage(new MasterSecretUnion(masterSecret),

View File

@ -65,6 +65,7 @@ public class MmsSmsDatabase extends Database {
AttachmentDatabase.THUMBNAIL, AttachmentDatabase.THUMBNAIL,
AttachmentDatabase.CONTENT_TYPE, AttachmentDatabase.CONTENT_TYPE,
AttachmentDatabase.CONTENT_LOCATION, AttachmentDatabase.CONTENT_LOCATION,
AttachmentDatabase.DIGEST,
AttachmentDatabase.CONTENT_DISPOSITION, AttachmentDatabase.CONTENT_DISPOSITION,
AttachmentDatabase.NAME, AttachmentDatabase.NAME,
AttachmentDatabase.TRANSFER_STATE}; AttachmentDatabase.TRANSFER_STATE};
@ -157,6 +158,7 @@ public class MmsSmsDatabase extends Database {
AttachmentDatabase.THUMBNAIL, AttachmentDatabase.THUMBNAIL,
AttachmentDatabase.CONTENT_TYPE, AttachmentDatabase.CONTENT_TYPE,
AttachmentDatabase.CONTENT_LOCATION, AttachmentDatabase.CONTENT_LOCATION,
AttachmentDatabase.DIGEST,
AttachmentDatabase.CONTENT_DISPOSITION, AttachmentDatabase.CONTENT_DISPOSITION,
AttachmentDatabase.NAME, AttachmentDatabase.NAME,
AttachmentDatabase.TRANSFER_STATE}; AttachmentDatabase.TRANSFER_STATE};
@ -183,6 +185,7 @@ public class MmsSmsDatabase extends Database {
AttachmentDatabase.THUMBNAIL, AttachmentDatabase.THUMBNAIL,
AttachmentDatabase.CONTENT_TYPE, AttachmentDatabase.CONTENT_TYPE,
AttachmentDatabase.CONTENT_LOCATION, AttachmentDatabase.CONTENT_LOCATION,
AttachmentDatabase.DIGEST,
AttachmentDatabase.CONTENT_DISPOSITION, AttachmentDatabase.CONTENT_DISPOSITION,
AttachmentDatabase.NAME, AttachmentDatabase.NAME,
AttachmentDatabase.TRANSFER_STATE}; AttachmentDatabase.TRANSFER_STATE};
@ -235,6 +238,7 @@ public class MmsSmsDatabase extends Database {
mmsColumnsPresent.add(AttachmentDatabase.THUMBNAIL); mmsColumnsPresent.add(AttachmentDatabase.THUMBNAIL);
mmsColumnsPresent.add(AttachmentDatabase.CONTENT_TYPE); mmsColumnsPresent.add(AttachmentDatabase.CONTENT_TYPE);
mmsColumnsPresent.add(AttachmentDatabase.CONTENT_LOCATION); mmsColumnsPresent.add(AttachmentDatabase.CONTENT_LOCATION);
mmsColumnsPresent.add(AttachmentDatabase.DIGEST);
mmsColumnsPresent.add(AttachmentDatabase.CONTENT_DISPOSITION); mmsColumnsPresent.add(AttachmentDatabase.CONTENT_DISPOSITION);
mmsColumnsPresent.add(AttachmentDatabase.NAME); mmsColumnsPresent.add(AttachmentDatabase.NAME);
mmsColumnsPresent.add(AttachmentDatabase.TRANSFER_STATE); mmsColumnsPresent.add(AttachmentDatabase.TRANSFER_STATE);

View File

@ -19,9 +19,11 @@ import org.thoughtcrime.securesms.events.PartProgressEvent;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.jobs.requirements.MediaNetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MediaNetworkRequirement;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.util.Hex;
import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.ProgressListener; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.ProgressListener;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
@ -149,7 +151,13 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
relay = attachment.getRelay(); relay = attachment.getRelay();
} }
return new SignalServiceAttachmentPointer(id, null, key, relay); if (attachment.getDigest() != null) {
Log.w(TAG, "Downloading attachment with digest: " + Hex.toString(attachment.getDigest()));
} else {
Log.w(TAG, "Downloading attachment with no digest...");
}
return new SignalServiceAttachmentPointer(id, null, key, relay, Optional.fromNullable(attachment.getDigest()));
} catch (InvalidMessageException | IOException e) { } catch (InvalidMessageException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
throw new InvalidPartException(e); throw new InvalidPartException(e);

View File

@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
@ -12,9 +13,11 @@ import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel; import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.BitmapDecodingException;
import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.Hex;
import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
@ -35,7 +38,7 @@ public class AvatarDownloadJob extends MasterSecretJob implements InjectableType
private final byte[] groupId; private final byte[] groupId;
public AvatarDownloadJob(Context context, byte[] groupId) { public AvatarDownloadJob(Context context, @NonNull byte[] groupId) {
super(context, JobParameters.newBuilder() super(context, JobParameters.newBuilder()
.withRequirement(new MasterSecretRequirement(context)) .withRequirement(new MasterSecretRequirement(context))
.withRequirement(new NetworkRequirement(context)) .withRequirement(new NetworkRequirement(context))
@ -56,21 +59,24 @@ public class AvatarDownloadJob extends MasterSecretJob implements InjectableType
try { try {
if (record != null) { if (record != null) {
long avatarId = record.getAvatarId(); long avatarId = record.getAvatarId();
String contentType = record.getAvatarContentType(); String contentType = record.getAvatarContentType();
byte[] key = record.getAvatarKey(); byte[] key = record.getAvatarKey();
String relay = record.getRelay(); String relay = record.getRelay();
Optional<byte[]> digest = Optional.fromNullable(record.getAvatarDigest());
if (avatarId == -1 || key == null) { if (avatarId == -1 || key == null) {
return; return;
} }
if (digest.isPresent()) {
Log.w(TAG, "Downloading group avatar with digest: " + Hex.toString(digest.get()));
}
attachment = File.createTempFile("avatar", "tmp", context.getCacheDir()); attachment = File.createTempFile("avatar", "tmp", context.getCacheDir());
attachment.deleteOnExit(); attachment.deleteOnExit();
SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, relay); SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, relay, digest);
InputStream inputStream = receiver.retrieveAttachment(pointer, attachment); InputStream inputStream = receiver.retrieveAttachment(pointer, attachment);
Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key), 500, 500); Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key), 500, 500);

View File

@ -10,6 +10,7 @@ import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.data.StreamLocalUriFetcher; import com.bumptech.glide.load.data.StreamLocalUriFetcher;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.crypto.AttachmentCipherInputStream; import org.whispersystems.signalservice.api.crypto.AttachmentCipherInputStream;
import java.io.File; import java.io.File;
@ -29,7 +30,7 @@ public class AttachmentStreamLocalUriFetcher implements DataFetcher<InputStream>
} }
@Override public InputStream loadData(Priority priority) throws Exception { @Override public InputStream loadData(Priority priority) throws Exception {
is = new AttachmentCipherInputStream(attachment, key); is = new AttachmentCipherInputStream(attachment, key, Optional.<byte[]>absent());
return is; return is;
} }