X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/ad509e8097733e91837338f6470441567f6970b2..d94a7511ddabe0ae19ec853e9422e0c52ae4f7c1:/src/main/java/org/asamk/signal/manager/Manager.java diff --git a/src/main/java/org/asamk/signal/manager/Manager.java b/src/main/java/org/asamk/signal/manager/Manager.java index 2ce59cdc..a4127b75 100644 --- a/src/main/java/org/asamk/signal/manager/Manager.java +++ b/src/main/java/org/asamk/signal/manager/Manager.java @@ -124,6 +124,7 @@ import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; @@ -267,6 +268,21 @@ public class Manager implements Closeable { account.setProfileKey(KeyUtils.createProfileKey()); account.save(); } + // Store profile keys only in profile store + for (ContactInfo contact : account.getContactStore().getContacts()) { + String profileKeyString = contact.profileKey; + if (profileKeyString == null) { + continue; + } + final ProfileKey profileKey; + try { + profileKey = new ProfileKey(Base64.decode(profileKeyString)); + } catch (InvalidInputException | IOException e) { + continue; + } + contact.profileKey = null; + account.getProfileStore().storeProfileKey(contact.getAddress(), profileKey); + } } public void checkAccountState() throws IOException { @@ -431,10 +447,9 @@ public class Manager implements Closeable { private SignalServiceMessageSender getMessageSender() { // TODO implement ZkGroup support final ClientZkProfileOperations clientZkProfileOperations = null; - final boolean attachmentsV3 = false; final ExecutorService executor = null; return new SignalServiceMessageSender(serviceConfiguration, account.getUuid(), account.getUsername(), account.getPassword(), - account.getDeviceId(), account.getSignalProtocolStore(), userAgent, account.isMultiDevice(), attachmentsV3, Optional.fromNullable(messagePipe), Optional.fromNullable(unidentifiedMessagePipe), Optional.absent(), clientZkProfileOperations, executor); + account.getDeviceId(), account.getSignalProtocolStore(), userAgent, account.isMultiDevice(), Optional.fromNullable(messagePipe), Optional.fromNullable(unidentifiedMessagePipe), Optional.absent(), clientZkProfileOperations, executor, ServiceConfig.MAX_ENVELOPE_SIZE); } private SignalServiceProfile getEncryptedRecipientProfile(SignalServiceAddress address, Optional unidentifiedAccess) throws IOException { @@ -843,7 +858,7 @@ public class Manager implements Closeable { String packId = messageSender.uploadStickerManifest(manifest, packKey); try { - return new URI("https", "signal.art", "/addstickers/", "pack_id=" + URLEncoder.encode(packId, "utf-8") + "&pack_key=" + URLEncoder.encode(Hex.toStringCondensed(packKey), "utf-8")) + return new URI("https", "signal.art", "/addstickers/", "pack_id=" + URLEncoder.encode(packId, StandardCharsets.UTF_8) + "&pack_key=" + URLEncoder.encode(Hex.toStringCondensed(packKey), StandardCharsets.UTF_8)) .toString(); } catch (URISyntaxException e) { throw new AssertionError(e); @@ -994,16 +1009,10 @@ public class Manager implements Closeable { } private byte[] getTargetUnidentifiedAccessKey(SignalServiceAddress recipient) { - ContactInfo contact = account.getContactStore().getContact(recipient); - if (contact == null || contact.profileKey == null) { + ProfileKey theirProfileKey = account.getProfileStore().getProfileKey(recipient); + if (theirProfileKey == null) { return null; } - ProfileKey theirProfileKey; - try { - theirProfileKey = new ProfileKey(Base64.decode(contact.profileKey)); - } catch (InvalidInputException | IOException e) { - throw new AssertionError(e); - } SignalProfile targetProfile; try { targetProfile = getRecipientProfile(recipient, Optional.absent(), theirProfileKey); @@ -1198,8 +1207,9 @@ public class Manager implements Closeable { SignalServiceSyncMessage syncMessage = SignalServiceSyncMessage.forSentTranscript(transcript); try { + long startTime = System.currentTimeMillis(); messageSender.sendMessage(syncMessage, unidentifiedAccess); - return SendMessageResult.success(recipient, unidentifiedAccess.isPresent(), false); + return SendMessageResult.success(recipient, unidentifiedAccess.isPresent(), false, System.currentTimeMillis() - startTime); } catch (UntrustedIdentityException e) { account.getSignalProtocolStore().saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), e.getIdentityKey(), TrustLevel.UNTRUSTED); return SendMessageResult.identityFailure(recipient, e.getIdentityKey()); @@ -1326,24 +1336,16 @@ public class Manager implements Closeable { } } if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) { + final ProfileKey profileKey; + try { + profileKey = new ProfileKey(message.getProfileKey().get()); + } catch (InvalidInputException e) { + throw new AssertionError(e); + } if (source.matches(account.getSelfAddress())) { - try { - this.account.setProfileKey(new ProfileKey(message.getProfileKey().get())); - } catch (InvalidInputException ignored) { - } - ContactInfo contact = account.getContactStore().getContact(source); - if (contact != null) { - contact.profileKey = Base64.encodeBytes(message.getProfileKey().get()); - account.getContactStore().updateContact(contact); - } - } else { - ContactInfo contact = account.getContactStore().getContact(source); - if (contact == null) { - contact = new ContactInfo(source); - } - contact.profileKey = Base64.encodeBytes(message.getProfileKey().get()); - account.getContactStore().updateContact(contact); + this.account.setProfileKey(profileKey); } + this.account.getProfileStore().storeProfileKey(source, profileKey); } if (message.getPreviews().isPresent()) { final List previews = message.getPreviews().get(); @@ -1398,7 +1400,15 @@ public class Manager implements Closeable { if (!envelope.isReceipt()) { try { content = decryptMessage(envelope); - } catch (Exception e) { + } catch (org.whispersystems.libsignal.UntrustedIdentityException e) { + return; + } catch (Exception er) { + // All other errors are not recoverable, so delete the cached message + try { + Files.delete(fileEntry.toPath()); + } catch (IOException e) { + System.err.println("Failed to delete cached message file “" + fileEntry + "”: " + e.getMessage()); + } return; } List actions = handleMessage(envelope, content, ignoreAttachments); @@ -1461,6 +1471,7 @@ public class Manager implements Closeable { e.printStackTrace(); } } + account.save(); queuedActions.clear(); queuedActions = null; } @@ -1476,6 +1487,7 @@ public class Manager implements Closeable { System.err.println("Ignoring error: " + e.getMessage()); continue; } + if (envelope.hasSource()) { // Store uuid if we don't have it already SignalServiceAddress source = envelope.getSourceAddress(); @@ -1510,7 +1522,8 @@ public class Manager implements Closeable { if (!(exception instanceof org.whispersystems.libsignal.UntrustedIdentityException)) { File cacheFile = null; try { - cacheFile = getMessageCacheFile(envelope.getSourceE164().get(), now, envelope.getTimestamp()); + String source = envelope.getSourceE164().isPresent() ? envelope.getSourceE164().get() : ""; + cacheFile = getMessageCacheFile(source, now, envelope.getTimestamp()); Files.delete(cacheFile.toPath()); // Try to delete directory if empty new File(getMessageCachePath()).delete(); @@ -1679,7 +1692,7 @@ public class Manager implements Closeable { contact.color = c.getColor().get(); } if (c.getProfileKey().isPresent()) { - contact.profileKey = Base64.encodeBytes(c.getProfileKey().get().serialize()); + account.getProfileStore().storeProfileKey(address, c.getProfileKey().get()); } if (c.getVerified().isPresent()) { final VerifiedMessage verifiedMessage = c.getVerified().get(); @@ -1863,11 +1876,7 @@ public class Manager implements Closeable { verifiedMessage = new VerifiedMessage(record.getAddress(), currentIdentity.getIdentityKey(), currentIdentity.getTrustLevel().toVerifiedState(), currentIdentity.getDateAdded().getTime()); } - ProfileKey profileKey = null; - try { - profileKey = record.profileKey == null ? null : new ProfileKey(Base64.decode(record.profileKey)); - } catch (InvalidInputException ignored) { - } + ProfileKey profileKey = account.getProfileStore().getProfileKey(record.getAddress()); out.write(new DeviceContact(record.getAddress(), Optional.fromNullable(record.name), createContactAvatarAttachment(record.number), Optional.fromNullable(record.color), Optional.fromNullable(verifiedMessage), Optional.fromNullable(profileKey), record.blocked,