mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 18:40:39 +00:00
Store retrieved storage manifest locally
This commit is contained in:
parent
87016f6ecf
commit
b292de8ae6
2 changed files with 58 additions and 8 deletions
|
@ -21,10 +21,13 @@ import org.whispersystems.signalservice.internal.storage.protos.AccountRecord;
|
|||
import org.whispersystems.signalservice.internal.storage.protos.ManifestRecord;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StorageHelper {
|
||||
|
||||
|
@ -56,11 +59,19 @@ public class StorageHelper {
|
|||
return;
|
||||
}
|
||||
|
||||
account.setStorageManifestVersion(manifest.get().getVersion());
|
||||
logger.trace("Remote storage manifest has {} records", manifest.get().getStorageIds().size());
|
||||
final var storageIds = manifest.get()
|
||||
.getStorageIds()
|
||||
.stream()
|
||||
.filter(id -> !id.isUnknown())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final var storageIds = manifest.get().getStorageIds().stream().filter(id -> !id.isUnknown()).toList();
|
||||
Optional<SignalStorageManifest> localManifest = account.getStorageManifest();
|
||||
localManifest.ifPresent(m -> m.getStorageIds().forEach(storageIds::remove));
|
||||
|
||||
logger.trace("Reading {} new records", manifest.get().getStorageIds().size());
|
||||
for (final var record : getSignalStorageRecords(storageIds)) {
|
||||
logger.debug("Reading record of type {}", record.getType());
|
||||
if (record.getType() == ManifestRecord.Identifier.Type.ACCOUNT_VALUE) {
|
||||
readAccountRecord(record);
|
||||
} else if (record.getType() == ManifestRecord.Identifier.Type.GROUPV2_VALUE) {
|
||||
|
@ -71,6 +82,8 @@ public class StorageHelper {
|
|||
readContactRecord(record);
|
||||
}
|
||||
}
|
||||
account.setStorageManifestVersion(manifest.get().getVersion());
|
||||
account.setStorageManifest(manifest.get());
|
||||
logger.debug("Done reading data from remote storage");
|
||||
}
|
||||
|
||||
|
@ -86,10 +99,12 @@ public class StorageHelper {
|
|||
final var contact = account.getContactStore().getContact(recipientId);
|
||||
final var blocked = contact != null && contact.isBlocked();
|
||||
final var profileShared = contact != null && contact.isProfileSharingEnabled();
|
||||
if (contactRecord.getGivenName().isPresent()
|
||||
|| contactRecord.getFamilyName().isPresent()
|
||||
|| blocked != contactRecord.isBlocked()
|
||||
|| profileShared != contactRecord.isProfileSharingEnabled()) {
|
||||
final var givenName = contact == null ? null : contact.getGivenName();
|
||||
final var familyName = contact == null ? null : contact.getFamilyName();
|
||||
if ((contactRecord.getGivenName().isPresent() && !contactRecord.getGivenName().get().equals(givenName)) || (
|
||||
contactRecord.getFamilyName().isPresent() && !contactRecord.getFamilyName().get().equals(familyName)
|
||||
) || blocked != contactRecord.isBlocked() || profileShared != contactRecord.isProfileSharingEnabled()) {
|
||||
logger.debug("Storing new or updated contact {}", recipientId);
|
||||
final var contactBuilder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
|
||||
final var newContact = contactBuilder.withBlocked(contactRecord.isBlocked())
|
||||
.withGivenName(contactRecord.getGivenName().orElse(null))
|
||||
|
@ -101,6 +116,7 @@ public class StorageHelper {
|
|||
|
||||
if (contactRecord.getProfileKey().isPresent()) {
|
||||
try {
|
||||
logger.trace("Storing profile key {}", recipientId);
|
||||
final var profileKey = new ProfileKey(contactRecord.getProfileKey().get());
|
||||
account.getProfileStore().storeProfileKey(recipientId, profileKey);
|
||||
} catch (InvalidInputException e) {
|
||||
|
@ -109,6 +125,7 @@ public class StorageHelper {
|
|||
}
|
||||
if (contactRecord.getIdentityKey().isPresent()) {
|
||||
try {
|
||||
logger.trace("Storing identity key {}", recipientId);
|
||||
final var identityKey = new IdentityKey(contactRecord.getIdentityKey().get());
|
||||
account.getIdentityKeyStore().saveIdentity(recipientId, identityKey, new Date());
|
||||
|
||||
|
@ -239,10 +256,11 @@ public class StorageHelper {
|
|||
return records.size() > 0 ? records.get(0) : null;
|
||||
}
|
||||
|
||||
private List<SignalStorageRecord> getSignalStorageRecords(final List<StorageId> storageIds) throws IOException {
|
||||
private List<SignalStorageRecord> getSignalStorageRecords(final Collection<StorageId> storageIds) throws IOException {
|
||||
List<SignalStorageRecord> records;
|
||||
try {
|
||||
records = dependencies.getAccountManager().readStorageRecords(account.getStorageKey(), storageIds);
|
||||
records = dependencies.getAccountManager()
|
||||
.readStorageRecords(account.getStorageKey(), new ArrayList<>(storageIds));
|
||||
} catch (InvalidKeyException e) {
|
||||
logger.warn("Failed to read storage records, ignoring.");
|
||||
return List.of();
|
||||
|
|
|
@ -59,6 +59,7 @@ import org.whispersystems.signalservice.api.push.PNI;
|
|||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
|
||||
import org.whispersystems.signalservice.api.storage.StorageKey;
|
||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
@ -67,6 +68,8 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.channels.Channels;
|
||||
|
@ -81,6 +84,7 @@ import java.util.Comparator;
|
|||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SignalAccount implements Closeable {
|
||||
|
@ -467,6 +471,10 @@ public class SignalAccount implements Closeable {
|
|||
return new File(getUserPath(dataPath, account), "recipients-store");
|
||||
}
|
||||
|
||||
private static File getStorageManifestFile(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "storage-manifest");
|
||||
}
|
||||
|
||||
private static File getDatabaseFile(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "account.db");
|
||||
}
|
||||
|
@ -1274,6 +1282,30 @@ public class SignalAccount implements Closeable {
|
|||
save();
|
||||
}
|
||||
|
||||
public Optional<SignalStorageManifest> getStorageManifest() {
|
||||
final var storageManifestFile = getStorageManifestFile(dataPath, accountPath);
|
||||
if (!storageManifestFile.exists()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try (var inputStream = new FileInputStream(storageManifestFile)) {
|
||||
return Optional.of(SignalStorageManifest.deserialize(inputStream.readAllBytes()));
|
||||
} catch (IOException e) {
|
||||
logger.warn("Failed to read local storage manifest.", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public void setStorageManifest(SignalStorageManifest manifest) {
|
||||
final var manifestBytes = manifest.serialize();
|
||||
|
||||
final var storageManifestFile = getStorageManifestFile(dataPath, accountPath);
|
||||
try (var outputStream = new FileOutputStream(storageManifestFile)) {
|
||||
outputStream.write(manifestBytes);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to store local storage manifest.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ProfileKey getProfileKey() {
|
||||
return profileKey;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue