mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 02:10:44 +01:00
Migrate avatars and group avatars.
This commit is contained in:
@@ -42,7 +42,6 @@ public class GroupDatabase extends Database {
|
||||
static final String RECIPIENT_ID = "recipient_id";
|
||||
private static final String TITLE = "title";
|
||||
private static final String MEMBERS = "members";
|
||||
private static final String AVATAR = "avatar";
|
||||
private static final String AVATAR_ID = "avatar_id";
|
||||
private static final String AVATAR_KEY = "avatar_key";
|
||||
private static final String AVATAR_CONTENT_TYPE = "avatar_content_type";
|
||||
@@ -59,7 +58,6 @@ public class GroupDatabase extends Database {
|
||||
RECIPIENT_ID + " INTEGER, " +
|
||||
TITLE + " TEXT, " +
|
||||
MEMBERS + " TEXT, " +
|
||||
AVATAR + " BLOB, " +
|
||||
AVATAR_ID + " INTEGER, " +
|
||||
AVATAR_KEY + " BLOB, " +
|
||||
AVATAR_CONTENT_TYPE + " TEXT, " +
|
||||
@@ -75,7 +73,7 @@ public class GroupDatabase extends Database {
|
||||
};
|
||||
|
||||
private static final String[] GROUP_PROJECTION = {
|
||||
GROUP_ID, RECIPIENT_ID, TITLE, MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
||||
GROUP_ID, RECIPIENT_ID, TITLE, MEMBERS, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
||||
TIMESTAMP, ACTIVE, MMS
|
||||
};
|
||||
|
||||
@@ -120,7 +118,7 @@ public class GroupDatabase extends Database {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean noMetadata = group.get().getAvatar() == null && TextUtils.isEmpty(group.get().getTitle());
|
||||
boolean noMetadata = !group.get().hasAvatar() && TextUtils.isEmpty(group.get().getTitle());
|
||||
boolean noMembers = group.get().getMembers().isEmpty() || (group.get().getMembers().size() == 1 && group.get().getMembers().contains(Recipient.self().getId()));
|
||||
|
||||
return noMetadata && noMembers;
|
||||
@@ -228,6 +226,8 @@ public class GroupDatabase extends Database {
|
||||
contentValues.put(AVATAR_KEY, avatar.getKey());
|
||||
contentValues.put(AVATAR_CONTENT_TYPE, avatar.getContentType());
|
||||
contentValues.put(AVATAR_DIGEST, avatar.getDigest().orNull());
|
||||
} else {
|
||||
contentValues.put(AVATAR_ID, 0);
|
||||
}
|
||||
|
||||
contentValues.put(AVATAR_RELAY, relay);
|
||||
@@ -252,6 +252,8 @@ public class GroupDatabase extends Database {
|
||||
contentValues.put(AVATAR_CONTENT_TYPE, avatar.getContentType());
|
||||
contentValues.put(AVATAR_KEY, avatar.getKey());
|
||||
contentValues.put(AVATAR_DIGEST, avatar.getDigest().orNull());
|
||||
} else {
|
||||
contentValues.put(AVATAR_ID, 0);
|
||||
}
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues,
|
||||
@@ -274,20 +276,12 @@ public class GroupDatabase extends Database {
|
||||
Recipient.live(groupRecipient).refresh();
|
||||
}
|
||||
|
||||
public void updateAvatar(@NonNull GroupId groupId, @Nullable Bitmap avatar) {
|
||||
updateAvatar(groupId, BitmapUtil.toByteArray(avatar));
|
||||
}
|
||||
|
||||
public void updateAvatar(@NonNull GroupId groupId, @Nullable byte[] avatar) {
|
||||
long avatarId;
|
||||
|
||||
if (avatar != null) avatarId = Math.abs(new SecureRandom().nextLong());
|
||||
else avatarId = 0;
|
||||
|
||||
|
||||
ContentValues contentValues = new ContentValues(2);
|
||||
contentValues.put(AVATAR, avatar);
|
||||
contentValues.put(AVATAR_ID, avatarId);
|
||||
/**
|
||||
* Used to bust the Glide cache when an avatar changes.
|
||||
*/
|
||||
public void onAvatarUpdated(@NonNull GroupId groupId, boolean hasAvatar) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(AVATAR_ID, hasAvatar ? Math.abs(new SecureRandom().nextLong()) : 0);
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||
new String[] {groupId.toString()});
|
||||
@@ -388,7 +382,6 @@ public class GroupDatabase extends Database {
|
||||
RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow(RECIPIENT_ID))),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(TITLE)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS)),
|
||||
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR)),
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(AVATAR_ID)),
|
||||
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_KEY)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_CONTENT_TYPE)),
|
||||
@@ -411,7 +404,6 @@ public class GroupDatabase extends Database {
|
||||
private final RecipientId recipientId;
|
||||
private final String title;
|
||||
private final List<RecipientId> members;
|
||||
private final byte[] avatar;
|
||||
private final long avatarId;
|
||||
private final byte[] avatarKey;
|
||||
private final byte[] avatarDigest;
|
||||
@@ -420,14 +412,13 @@ public class GroupDatabase extends Database {
|
||||
private final boolean active;
|
||||
private final boolean mms;
|
||||
|
||||
public GroupRecord(@NonNull GroupId id, @NonNull RecipientId recipientId, String title, String members, byte[] avatar,
|
||||
public GroupRecord(@NonNull GroupId id, @NonNull RecipientId recipientId, String title, String members,
|
||||
long avatarId, byte[] avatarKey, String avatarContentType,
|
||||
String relay, boolean active, byte[] avatarDigest, boolean mms)
|
||||
{
|
||||
this.id = id;
|
||||
this.recipientId = recipientId;
|
||||
this.title = title;
|
||||
this.avatar = avatar;
|
||||
this.avatarId = avatarId;
|
||||
this.avatarKey = avatarKey;
|
||||
this.avatarDigest = avatarDigest;
|
||||
@@ -456,8 +447,8 @@ public class GroupDatabase extends Database {
|
||||
return members;
|
||||
}
|
||||
|
||||
public byte[] getAvatar() {
|
||||
return avatar;
|
||||
public boolean hasAvatar() {
|
||||
return avatarId != 0;
|
||||
}
|
||||
|
||||
public long getAvatarId() {
|
||||
|
||||
@@ -21,7 +21,9 @@ import net.sqlcipher.database.SQLiteDatabase;
|
||||
import net.sqlcipher.database.SQLiteDatabaseHook;
|
||||
import net.sqlcipher.database.SQLiteOpenHelper;
|
||||
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.profiles.ProfileName;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
@@ -51,14 +53,17 @@ import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.FileUtils;
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.SqlUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
@@ -118,8 +123,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int GROUPS_V2_RECIPIENT_CAPABILITY = 51;
|
||||
private static final int TRANSFER_FILE_CLEANUP = 52;
|
||||
private static final int PROFILE_DATA_MIGRATION = 53;
|
||||
private static final int AVATAR_LOCATION_MIGRATION = 54;
|
||||
|
||||
private static final int DATABASE_VERSION = 53;
|
||||
private static final int DATABASE_VERSION = 54;
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
@@ -802,6 +808,49 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (oldVersion < AVATAR_LOCATION_MIGRATION) {
|
||||
File oldAvatarDirectory = new File(context.getFilesDir(), "avatars");
|
||||
File[] results = oldAvatarDirectory.listFiles();
|
||||
|
||||
if (results != null) {
|
||||
Log.i(TAG, "Preparing to migrate " + results.length + " avatars.");
|
||||
|
||||
for (File file : results) {
|
||||
if (Util.isLong(file.getName())) {
|
||||
try {
|
||||
AvatarHelper.setAvatar(context, RecipientId.from(file.getName()), new FileInputStream(file));
|
||||
} catch(IOException e) {
|
||||
Log.w(TAG, "Failed to copy file " + file.getName() + "! Skipping.");
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Invalid avatar name '" + file.getName() + "'! Skipping.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "No avatar directory files found.");
|
||||
}
|
||||
|
||||
if (!FileUtils.deleteDirectory(oldAvatarDirectory)) {
|
||||
Log.w(TAG, "Failed to delete avatar directory.");
|
||||
}
|
||||
|
||||
try (Cursor cursor = db.rawQuery("SELECT recipient_id, avatar FROM groups", null)) {
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
RecipientId recipientId = RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow("recipient_id")));
|
||||
byte[] avatar = cursor.getBlob(cursor.getColumnIndexOrThrow("avatar"));
|
||||
|
||||
try {
|
||||
AvatarHelper.setAvatar(context, recipientId, avatar != null ? new ByteArrayInputStream(avatar) : null);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Failed to copy avatar for " + recipientId + "! Skipping.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
db.execSQL("UPDATE groups SET avatar_id = 0 WHERE avatar IS NULL");
|
||||
db.execSQL("UPDATE groups SET avatar = NULL");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
||||
Reference in New Issue
Block a user