From 9f3276d7e359cf681a42c675ad376977d5957395 Mon Sep 17 00:00:00 2001 From: AsamK Date: Fri, 19 Feb 2021 17:56:43 +0100 Subject: [PATCH 01/16] Reformat code --- src/main/java/org/asamk/Signal.java | 4 +++- .../java/org/asamk/signal/dbus/DbusSignalImpl.java | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asamk/Signal.java b/src/main/java/org/asamk/Signal.java index 1c7d9f1c..3bd1c0d7 100644 --- a/src/main/java/org/asamk/Signal.java +++ b/src/main/java/org/asamk/Signal.java @@ -51,7 +51,9 @@ public interface Signal extends DBusInterface { boolean isRegistered(); - void updateProfile(String name,String about,String aboutEmoji,String avatarPath,boolean removeAvatar) throws Error.Failure; + void updateProfile( + String name, String about, String aboutEmoji, String avatarPath, boolean removeAvatar + ) throws Error.Failure; class MessageReceived extends DBusSignal { diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 4f23d461..4af7156d 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -10,11 +10,10 @@ import org.asamk.signal.manager.storage.groups.GroupInfo; import org.asamk.signal.util.ErrorUtils; import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.whispersystems.libsignal.util.Pair; +import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.InvalidNumberException; -import org.whispersystems.libsignal.util.guava.Optional; -import org.asamk.signal.manager.storage.contacts.ContactInfo; import java.io.File; import java.io.IOException; @@ -252,9 +251,15 @@ public class DbusSignalImpl implements Signal { } @Override - public void updateProfile(final String name,final String about,final String aboutEmoji, String avatarPath, final boolean removeAvatar) { + public void updateProfile( + final String name, + final String about, + final String aboutEmoji, + String avatarPath, + final boolean removeAvatar + ) { try { - if (avatarPath.isEmpty()) { + if (avatarPath.isEmpty()) { avatarPath = null; } Optional avatarFile = removeAvatar -- 2.51.0 From 237abe431bb77436ef7a23d32339804fff592cc7 Mon Sep 17 00:00:00 2001 From: Atomic-Bean <75401809+Atomic-Bean@users.noreply.github.com> Date: Sat, 20 Feb 2021 03:33:15 +1030 Subject: [PATCH 02/16] Output "SharedContacts" field from a SignalDataMessage (#529) * Initial version of SharedContacts from data message. Need to change location of avatar downloaded and fix plain text mode * Made empty strings for json null and fixed plaintext output * Removed old comments, simplified if-statement and added a 'leadingSpaces' field to the print attachments/mentions functions * Added AsamK's changes --- .../org/asamk/signal/manager/Manager.java | 16 +- .../asamk/signal/ReceiveMessageHandler.java | 153 +++++++++++++++--- .../asamk/signal/json/JsonContactAddress.java | 48 ++++++ .../asamk/signal/json/JsonContactAvatar.java | 19 +++ .../asamk/signal/json/JsonContactEmail.java | 24 +++ .../asamk/signal/json/JsonContactName.java | 36 +++++ .../asamk/signal/json/JsonContactPhone.java | 24 +++ .../asamk/signal/json/JsonDataMessage.java | 20 ++- .../asamk/signal/json/JsonSharedContact.java | 75 +++++++++ src/main/java/org/asamk/signal/util/Util.java | 9 ++ 10 files changed, 399 insertions(+), 25 deletions(-) create mode 100644 src/main/java/org/asamk/signal/json/JsonContactAddress.java create mode 100644 src/main/java/org/asamk/signal/json/JsonContactAvatar.java create mode 100644 src/main/java/org/asamk/signal/json/JsonContactEmail.java create mode 100644 src/main/java/org/asamk/signal/json/JsonContactName.java create mode 100644 src/main/java/org/asamk/signal/json/JsonContactPhone.java create mode 100644 src/main/java/org/asamk/signal/json/JsonSharedContact.java diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index 9661b12c..80ff4e71 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -122,6 +122,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptM import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage; import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage; +import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.SignalServiceAddress; @@ -1553,9 +1554,18 @@ public class Manager implements Closeable { } } } - if (message.getAttachments().isPresent() && !ignoreAttachments) { - for (SignalServiceAttachment attachment : message.getAttachments().get()) { - downloadAttachment(attachment); + if (!ignoreAttachments) { + if (message.getAttachments().isPresent()) { + for (SignalServiceAttachment attachment : message.getAttachments().get()) { + downloadAttachment(attachment); + } + } + if (message.getSharedContacts().isPresent()) { + for (SharedContact contact : message.getSharedContacts().get()) { + if (contact.getAvatar().isPresent()) { + downloadAttachment(contact.getAvatar().get().getAttachment()); + } + } } } if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) { diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java index 07dbfd1d..9ab752cf 100644 --- a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java @@ -117,11 +117,11 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } else { System.out.println("Received sync contacts"); } - printAttachment(contactsMessage.getContactsStream()); + printAttachment(contactsMessage.getContactsStream(), 0); } if (syncMessage.getGroups().isPresent()) { System.out.println("Received sync groups"); - printAttachment(syncMessage.getGroups().get()); + printAttachment(syncMessage.getGroups().get(), 0); } if (syncMessage.getRead().isPresent()) { System.out.println("Received sync read messages list"); @@ -393,7 +393,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } if (groupInfo.getAvatar().isPresent()) { System.out.println(" Avatar:"); - printAttachment(groupInfo.getAvatar().get()); + printAttachment(groupInfo.getAvatar().get(), 2); } } else if (groupContext.getGroupV2().isPresent()) { final SignalServiceGroupV2 groupInfo = groupContext.getGroupV2().get(); @@ -421,7 +421,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { System.out.println(" - Title: " + preview.getTitle()); System.out.println(" - Url: " + preview.getUrl()); if (preview.getImage().isPresent()) { - printAttachment(preview.getImage().get()); + printAttachment(preview.getImage().get(), 1); } } } @@ -429,8 +429,106 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { final List sharedContacts = message.getSharedContacts().get(); System.out.println("Contacts:"); for (SharedContact contact : sharedContacts) { - System.out.println(" - Name: " + contact.getName()); - // TODO show or store rest of the contact info + System.out.println(" - Name:"); + SharedContact.Name name = contact.getName(); + if (name.getDisplay().isPresent() && !name.getDisplay().get().isBlank()) { + System.out.println(" - Display name: " + name.getDisplay().get()); + } + if (name.getGiven().isPresent() && !name.getGiven().get().isBlank()) { + System.out.println(" - First name: " + name.getGiven().get()); + } + if (name.getMiddle().isPresent() && !name.getMiddle().get().isBlank()) { + System.out.println(" - Middle name: " + name.getMiddle().get()); + } + if (name.getFamily().isPresent() && !name.getFamily().get().isBlank()) { + System.out.println(" - Family name: " + name.getFamily().get()); + } + if (name.getPrefix().isPresent() && !name.getPrefix().get().isBlank()) { + System.out.println(" - Prefix name: " + name.getPrefix().get()); + } + if (name.getSuffix().isPresent() && !name.getSuffix().get().isBlank()) { + System.out.println(" - Suffix name: " + name.getSuffix().get()); + } + + if (contact.getAvatar().isPresent()) { + SharedContact.Avatar avatar = contact.getAvatar().get(); + System.out.println(" - Avatar:"); + printAttachment(avatar.getAttachment(), 3); + if (avatar.isProfile()) { + System.out.println(" - Is profile"); + } else { + System.out.println(" - Is not a profile"); + } + } + + if (contact.getPhone().isPresent()) { + System.out.println(" - Phone details:"); + for (SharedContact.Phone phone : contact.getPhone().get()) { + System.out.println(" - Phone:"); + if (phone.getValue() != null) { + System.out.println(" - Number: " + phone.getValue()); + } + if (phone.getType() != null) { + System.out.println(" - Type: " + phone.getType()); + } + if (phone.getLabel().isPresent() && !phone.getLabel().get().isBlank()) { + System.out.println(" - Label: " + phone.getLabel().get()); + } + } + } + + if (contact.getEmail().isPresent()) { + System.out.println(" - Email details:"); + for (SharedContact.Email email : contact.getEmail().get()) { + System.out.println(" - Email:"); + if (email.getValue() != null) { + System.out.println(" - Value: " + email.getValue()); + } + if (email.getType() != null) { + System.out.println(" - Type: " + email.getType()); + } + if (email.getLabel().isPresent() && !email.getLabel().get().isBlank()) { + System.out.println(" - Label: " + email.getLabel().get()); + } + } + } + + if (contact.getAddress().isPresent()) { + System.out.println(" - Address details:"); + for (SharedContact.PostalAddress address : contact.getAddress().get()) { + System.out.println(" - Address:"); + if (address.getType() != null) { + System.out.println(" - Type: " + address.getType()); + } + if (address.getLabel().isPresent() && !address.getLabel().get().isBlank()) { + System.out.println(" - Label: " + address.getLabel().get()); + } + if (address.getStreet().isPresent() && !address.getStreet().get().isBlank()) { + System.out.println(" - Street: " + address.getStreet().get()); + } + if (address.getPobox().isPresent() && !address.getPobox().get().isBlank()) { + System.out.println(" - Pobox: " + address.getPobox().get()); + } + if (address.getNeighborhood().isPresent() && !address.getNeighborhood().get().isBlank()) { + System.out.println(" - Neighbourhood: " + address.getNeighborhood().get()); + } + if (address.getCity().isPresent() && !address.getCity().get().isBlank()) { + System.out.println(" - City: " + address.getCity().get()); + } + if (address.getRegion().isPresent() && !address.getRegion().get().isBlank()) { + System.out.println(" - Region: " + address.getRegion().get()); + } + if (address.getPostcode().isPresent() && !address.getPostcode().get().isBlank()) { + System.out.println(" - Postcode: " + address.getPostcode().get()); + } + if (address.getCountry().isPresent() && !address.getCountry().get().isBlank()) { + System.out.println(" - Country: " + address.getCountry().get()); + } + } + } + + System.out.println(" - Organisation: " + + (contact.getOrganization().isPresent() ? contact.getOrganization().get() : "-")); } } if (message.getSticker().isPresent()) { @@ -472,7 +570,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { if (quote.getMentions() != null && quote.getMentions().size() > 0) { System.out.println(" Mentions: "); for (SignalServiceDataMessage.Mention mention : quote.getMentions()) { - printMention(mention, m); + printMention(mention, m, 1); } } if (quote.getAttachments().size() > 0) { @@ -482,7 +580,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { System.out.println(" Type: " + attachment.getContentType()); System.out.println(" Thumbnail:"); if (attachment.getThumbnail() != null) { - printAttachment(attachment.getThumbnail()); + printAttachment(attachment.getThumbnail(), 3); } } } @@ -495,45 +593,60 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { if (message.getMentions().isPresent()) { System.out.println("Mentions: "); for (SignalServiceDataMessage.Mention mention : message.getMentions().get()) { - printMention(mention, m); + printMention(mention, m, 0); } } if (message.getAttachments().isPresent()) { System.out.println("Attachments: "); for (SignalServiceAttachment attachment : message.getAttachments().get()) { - printAttachment(attachment); + printAttachment(attachment, 0); } } } - private void printMention(SignalServiceDataMessage.Mention mention, Manager m) { - System.out.println("- " + m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), null)) + /** + * Prints the Signal mention information + * + * @param mention is the Signal mention to print + * @param m is the Manager. used to resolve UUIDs into phone numbers if possible + * @param leadingSpaces is the number of spaces you want the message to be indented by + */ + private void printMention(SignalServiceDataMessage.Mention mention, Manager m, int leadingSpaces) { + String spaces = " ".repeat(leadingSpaces); + System.out.println(spaces + "- " + m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), null)) .getLegacyIdentifier() + ": " + mention.getStart() + " (length: " + mention.getLength() + ")"); } - private void printAttachment(SignalServiceAttachment attachment) { - System.out.println("- " + attachment.getContentType() + " (" + (attachment.isPointer() ? "Pointer" : "") + ( + /** + * Prints the Signal attachment information + * + * @param attachment is the Signal attachment to print + * @param leadingSpaces is the number of spaces you want the message to be indented by + */ + private void printAttachment(SignalServiceAttachment attachment, int leadingSpaces) { + String spaces = " ".repeat(leadingSpaces); + System.out.println(spaces + "- " + attachment.getContentType() + " (" + (attachment.isPointer() ? "Pointer" : "") + ( attachment.isStream() ? "Stream" : "" ) + ")"); if (attachment.isPointer()) { final SignalServiceAttachmentPointer pointer = attachment.asPointer(); - System.out.println(" Id: " + pointer.getRemoteId() + " Key length: " + pointer.getKey().length); - System.out.println(" Filename: " + ( + System.out.println(spaces + " Id: " + pointer.getRemoteId() + " Key length: " + pointer.getKey().length); + System.out.println(spaces + " Filename: " + ( pointer.getFileName().isPresent() ? pointer.getFileName().get() : "-" )); - System.out.println(" Size: " + ( + System.out.println(spaces + " Size: " + ( pointer.getSize().isPresent() ? pointer.getSize().get() + " bytes" : "" ) + ( pointer.getPreview().isPresent() ? " (Preview is available: " + pointer.getPreview().get().length + " bytes)" : "" )); - System.out.println(" Voice note: " + (pointer.getVoiceNote() ? "yes" : "no")); - System.out.println(" Dimensions: " + pointer.getWidth() + "x" + pointer.getHeight()); + System.out.println(spaces + " Voice note: " + (pointer.getVoiceNote() ? "yes" : "no")); + System.out.println(spaces + " Dimensions: " + pointer.getWidth() + "x" + pointer.getHeight()); File file = m.getAttachmentFile(pointer.getRemoteId()); if (file.exists()) { - System.out.println(" Stored plaintext in: " + file); + System.out.println(spaces + " Stored plaintext in: " + file); } } } diff --git a/src/main/java/org/asamk/signal/json/JsonContactAddress.java b/src/main/java/org/asamk/signal/json/JsonContactAddress.java new file mode 100644 index 00000000..712dd4f3 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactAddress.java @@ -0,0 +1,48 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.asamk.signal.util.Util; +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactAddress { + + @JsonProperty + private final SharedContact.PostalAddress.Type type; + + @JsonProperty + private final String label; + + @JsonProperty + private final String street; + + @JsonProperty + private final String pobox; + + @JsonProperty + private final String neighborhood; + + @JsonProperty + private final String city; + + @JsonProperty + private final String region; + + @JsonProperty + private final String postcode; + + @JsonProperty + private final String country; + + public JsonContactAddress(SharedContact.PostalAddress address) { + type = address.getType(); + label = Util.getStringIfNotBlank(address.getLabel()); + street = Util.getStringIfNotBlank(address.getStreet()); + pobox = Util.getStringIfNotBlank(address.getPobox()); + neighborhood = Util.getStringIfNotBlank(address.getNeighborhood()); + city = Util.getStringIfNotBlank(address.getCity()); + region = Util.getStringIfNotBlank(address.getRegion()); + postcode = Util.getStringIfNotBlank(address.getPostcode()); + country = Util.getStringIfNotBlank(address.getCountry()); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonContactAvatar.java b/src/main/java/org/asamk/signal/json/JsonContactAvatar.java new file mode 100644 index 00000000..3ed55f6f --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactAvatar.java @@ -0,0 +1,19 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactAvatar { + + @JsonProperty + private final JsonAttachment attachment; + + @JsonProperty + private final boolean isProfile; + + public JsonContactAvatar(SharedContact.Avatar avatar) { + attachment = new JsonAttachment(avatar.getAttachment()); + isProfile = avatar.isProfile(); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonContactEmail.java b/src/main/java/org/asamk/signal/json/JsonContactEmail.java new file mode 100644 index 00000000..070cfb72 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactEmail.java @@ -0,0 +1,24 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.asamk.signal.util.Util; +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactEmail { + + @JsonProperty + private final String value; + + @JsonProperty + private final SharedContact.Email.Type type; + + @JsonProperty + private final String label; + + public JsonContactEmail(SharedContact.Email email) { + value = email.getValue(); + type = email.getType(); + label = Util.getStringIfNotBlank(email.getLabel()); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonContactName.java b/src/main/java/org/asamk/signal/json/JsonContactName.java new file mode 100644 index 00000000..9da27825 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactName.java @@ -0,0 +1,36 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.asamk.signal.util.Util; +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactName { + + @JsonProperty + private final String display; + + @JsonProperty + private final String given; + + @JsonProperty + private final String family; + + @JsonProperty + private final String prefix; + + @JsonProperty + private final String suffix; + + @JsonProperty + private final String middle; + + public JsonContactName(SharedContact.Name name) { + display = Util.getStringIfNotBlank(name.getDisplay()); + given = Util.getStringIfNotBlank(name.getGiven()); + family = Util.getStringIfNotBlank(name.getFamily()); + prefix = Util.getStringIfNotBlank(name.getPrefix()); + suffix = Util.getStringIfNotBlank(name.getSuffix()); + middle = Util.getStringIfNotBlank(name.getMiddle()); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonContactPhone.java b/src/main/java/org/asamk/signal/json/JsonContactPhone.java new file mode 100644 index 00000000..fce75843 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactPhone.java @@ -0,0 +1,24 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.asamk.signal.util.Util; +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactPhone { + + @JsonProperty + private final String value; + + @JsonProperty + private final SharedContact.Phone.Type type; + + @JsonProperty + private final String label; + + public JsonContactPhone(SharedContact.Phone phone) { + value = phone.getValue(); + type = phone.getType(); + label = Util.getStringIfNotBlank(phone.getLabel()); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonDataMessage.java b/src/main/java/org/asamk/signal/json/JsonDataMessage.java index 1c927b40..57facc99 100644 --- a/src/main/java/org/asamk/signal/json/JsonDataMessage.java +++ b/src/main/java/org/asamk/signal/json/JsonDataMessage.java @@ -52,6 +52,10 @@ class JsonDataMessage { @JsonInclude(JsonInclude.Include.NON_NULL) final JsonRemoteDelete remoteDelete; + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + final List contacts; + @JsonProperty @JsonInclude(JsonInclude.Include.NON_NULL) final JsonGroupInfo groupInfo; @@ -100,6 +104,16 @@ class JsonDataMessage { this.attachments = List.of(); } this.sticker = dataMessage.getSticker().isPresent() ? new JsonSticker(dataMessage.getSticker().get()) : null; + + if (dataMessage.getSharedContacts().isPresent()) { + this.contacts = dataMessage.getSharedContacts() + .get() + .stream() + .map(JsonSharedContact::new) + .collect(Collectors.toList()); + } else { + this.contacts = List.of(); + } } public JsonDataMessage(Signal.MessageReceived messageReceived) { @@ -109,10 +123,11 @@ class JsonDataMessage { expiresInSeconds = null; viewOnce = null; remoteDelete = null; - reaction = null; // TODO Replace these 4 with the proper commands + reaction = null; // TODO Replace these 5 with the proper commands quote = null; mentions = null; sticker = null; + contacts = null; attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList()); } @@ -123,10 +138,11 @@ class JsonDataMessage { expiresInSeconds = null; viewOnce = null; remoteDelete = null; - reaction = null; // TODO Replace these 4 with the proper commands + reaction = null; // TODO Replace these 5 with the proper commands quote = null; mentions = null; sticker = null; + contacts = null; attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList()); } } diff --git a/src/main/java/org/asamk/signal/json/JsonSharedContact.java b/src/main/java/org/asamk/signal/json/JsonSharedContact.java new file mode 100644 index 00000000..b1b7718c --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonSharedContact.java @@ -0,0 +1,75 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +import java.util.List; +import java.util.stream.Collectors; + +public class JsonSharedContact { + + @JsonProperty + final JsonContactName name; + + @JsonProperty + final JsonContactAvatar avatar; + + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + final List phone; + + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + final List email; + + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + final List address; + + @JsonProperty + final String organization; + + + public JsonSharedContact(SharedContact contact) { + name = new JsonContactName(contact.getName()); + if (contact.getAvatar().isPresent()) { + avatar = new JsonContactAvatar(contact.getAvatar().get()); + } else { + avatar = null; + } + + if (contact.getPhone().isPresent()) { + phone = contact.getPhone() + .get() + .stream() + .map(JsonContactPhone::new) + .collect(Collectors.toList()); + } else { + phone = null; + } + + if (contact.getEmail().isPresent()) { + email = contact.getEmail() + .get() + .stream() + .map(JsonContactEmail::new) + .collect(Collectors.toList()); + } else { + email = null; + } + + if (contact.getAddress().isPresent()) { + address = contact.getAddress() + .get() + .stream() + .map(JsonContactAddress::new) + .collect(Collectors.toList()); + } else { + address = null; + } + + organization = contact.getOrganization().orNull(); + } +} diff --git a/src/main/java/org/asamk/signal/util/Util.java b/src/main/java/org/asamk/signal/util/Util.java index 92bfae7b..e798d537 100644 --- a/src/main/java/org/asamk/signal/util/Util.java +++ b/src/main/java/org/asamk/signal/util/Util.java @@ -2,12 +2,21 @@ package org.asamk.signal.util; import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupIdFormatException; +import org.whispersystems.libsignal.util.guava.Optional; public class Util { private Util() { } + public static String getStringIfNotBlank(Optional value) { + String string = value.orNull(); + if (string == null || string.isBlank()) { + return null; + } + return string; + } + public static String formatSafetyNumber(String digits) { final int partCount = 12; int partSize = digits.length() / partCount; -- 2.51.0 From 6c33a89f82ffac98454c6f854e1c8877e3941f6a Mon Sep 17 00:00:00 2001 From: AsamK Date: Fri, 19 Feb 2021 18:04:08 +0100 Subject: [PATCH 03/16] Reformat code --- .../asamk/signal/ReceiveMessageHandler.java | 19 +++++++++++-------- .../asamk/signal/json/JsonSharedContact.java | 19 +++---------------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java index 9ab752cf..c3bede8b 100644 --- a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java @@ -527,8 +527,9 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } } - System.out.println(" - Organisation: " + - (contact.getOrganization().isPresent() ? contact.getOrganization().get() : "-")); + System.out.println(" - Organisation: " + ( + contact.getOrganization().isPresent() ? contact.getOrganization().get() : "-" + )); } } if (message.getSticker().isPresent()) { @@ -608,25 +609,27 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { /** * Prints the Signal mention information * - * @param mention is the Signal mention to print - * @param m is the Manager. used to resolve UUIDs into phone numbers if possible + * @param mention is the Signal mention to print + * @param m is the Manager. used to resolve UUIDs into phone numbers if possible * @param leadingSpaces is the number of spaces you want the message to be indented by */ private void printMention(SignalServiceDataMessage.Mention mention, Manager m, int leadingSpaces) { String spaces = " ".repeat(leadingSpaces); - System.out.println(spaces + "- " + m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), null)) - .getLegacyIdentifier() + ": " + mention.getStart() + " (length: " + mention.getLength() + ")"); + System.out.println(spaces + "- " + m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), + null)).getLegacyIdentifier() + ": " + mention.getStart() + " (length: " + mention.getLength() + ")"); } /** * Prints the Signal attachment information * - * @param attachment is the Signal attachment to print + * @param attachment is the Signal attachment to print * @param leadingSpaces is the number of spaces you want the message to be indented by */ private void printAttachment(SignalServiceAttachment attachment, int leadingSpaces) { String spaces = " ".repeat(leadingSpaces); - System.out.println(spaces + "- " + attachment.getContentType() + " (" + (attachment.isPointer() ? "Pointer" : "") + ( + System.out.println(spaces + "- " + attachment.getContentType() + " (" + ( + attachment.isPointer() ? "Pointer" : "" + ) + ( attachment.isStream() ? "Stream" : "" ) + ")"); if (attachment.isPointer()) { diff --git a/src/main/java/org/asamk/signal/json/JsonSharedContact.java b/src/main/java/org/asamk/signal/json/JsonSharedContact.java index b1b7718c..ea15b574 100644 --- a/src/main/java/org/asamk/signal/json/JsonSharedContact.java +++ b/src/main/java/org/asamk/signal/json/JsonSharedContact.java @@ -31,7 +31,6 @@ public class JsonSharedContact { @JsonProperty final String organization; - public JsonSharedContact(SharedContact contact) { name = new JsonContactName(contact.getName()); if (contact.getAvatar().isPresent()) { @@ -41,31 +40,19 @@ public class JsonSharedContact { } if (contact.getPhone().isPresent()) { - phone = contact.getPhone() - .get() - .stream() - .map(JsonContactPhone::new) - .collect(Collectors.toList()); + phone = contact.getPhone().get().stream().map(JsonContactPhone::new).collect(Collectors.toList()); } else { phone = null; } if (contact.getEmail().isPresent()) { - email = contact.getEmail() - .get() - .stream() - .map(JsonContactEmail::new) - .collect(Collectors.toList()); + email = contact.getEmail().get().stream().map(JsonContactEmail::new).collect(Collectors.toList()); } else { email = null; } if (contact.getAddress().isPresent()) { - address = contact.getAddress() - .get() - .stream() - .map(JsonContactAddress::new) - .collect(Collectors.toList()); + address = contact.getAddress().get().stream().map(JsonContactAddress::new).collect(Collectors.toList()); } else { address = null; } -- 2.51.0 From 03c30519b11e9772eecdc74f89d350bdecd20361 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 20 Feb 2021 19:22:36 +0100 Subject: [PATCH 04/16] Refactor ReceiveMessageHandler Introduce PlainTextWriter to improve indentation handling. --- .../asamk/signal/manager/groups/GroupId.java | 2 +- .../java/org/asamk/signal/JsonWriter.java | 6 +- .../org/asamk/signal/PlainTextWriter.java | 23 + .../org/asamk/signal/PlainTextWriterImpl.java | 67 ++ .../asamk/signal/ReceiveMessageHandler.java | 1046 +++++++++-------- .../java/org/asamk/signal/util/DateUtils.java | 2 +- 6 files changed, 640 insertions(+), 506 deletions(-) create mode 100644 src/main/java/org/asamk/signal/PlainTextWriter.java create mode 100644 src/main/java/org/asamk/signal/PlainTextWriterImpl.java diff --git a/lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java b/lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java index f56e5d38..5c5d639c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java +++ b/lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java @@ -33,7 +33,7 @@ public abstract class GroupId { } } - public GroupId(final byte[] id) { + protected GroupId(final byte[] id) { this.id = id; } diff --git a/src/main/java/org/asamk/signal/JsonWriter.java b/src/main/java/org/asamk/signal/JsonWriter.java index 26a20a1f..8aed4487 100644 --- a/src/main/java/org/asamk/signal/JsonWriter.java +++ b/src/main/java/org/asamk/signal/JsonWriter.java @@ -6,18 +6,20 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.io.Writer; import java.nio.charset.StandardCharsets; public class JsonWriter { - private final OutputStreamWriter writer; + private final Writer writer; private final ObjectMapper objectMapper; public JsonWriter(final OutputStream writer) { - this.writer = new OutputStreamWriter(writer, StandardCharsets.UTF_8); + this.writer = new BufferedWriter(new OutputStreamWriter(writer, StandardCharsets.UTF_8)); objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.PUBLIC_ONLY); diff --git a/src/main/java/org/asamk/signal/PlainTextWriter.java b/src/main/java/org/asamk/signal/PlainTextWriter.java new file mode 100644 index 00000000..91a4dbba --- /dev/null +++ b/src/main/java/org/asamk/signal/PlainTextWriter.java @@ -0,0 +1,23 @@ +package org.asamk.signal; + +import java.io.IOException; + +public interface PlainTextWriter { + + void println(String format, Object... args) throws IOException; + + PlainTextWriter indentedWriter(); + + default void println() throws IOException { + println(""); + } + + default void indent(final WriterConsumer subWriter) throws IOException { + subWriter.consume(indentedWriter()); + } + + interface WriterConsumer { + + void consume(PlainTextWriter writer) throws IOException; + } +} diff --git a/src/main/java/org/asamk/signal/PlainTextWriterImpl.java b/src/main/java/org/asamk/signal/PlainTextWriterImpl.java new file mode 100644 index 00000000..19874d55 --- /dev/null +++ b/src/main/java/org/asamk/signal/PlainTextWriterImpl.java @@ -0,0 +1,67 @@ +package org.asamk.signal; + +import org.slf4j.helpers.MessageFormatter; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; + +public final class PlainTextWriterImpl implements PlainTextWriter { + + private final Writer writer; + + private PlainTextWriter indentedWriter; + + public PlainTextWriterImpl(final OutputStream outputStream) { + this.writer = new BufferedWriter(new OutputStreamWriter(outputStream)); + } + + @Override + public void println(String format, Object... args) throws IOException { + final String message = MessageFormatter.arrayFormat(format, args).getMessage(); + + writer.write(message); + writer.write(System.lineSeparator()); + writer.flush(); + } + + @Override + public PlainTextWriter indentedWriter() { + if (indentedWriter == null) { + indentedWriter = new IndentedPlainTextWriter(this, writer); + } + return indentedWriter; + } + + private static final class IndentedPlainTextWriter implements PlainTextWriter { + + private final static int INDENTATION = 2; + + private final String spaces = " ".repeat(INDENTATION); + private final PlainTextWriter plainTextWriter; + private final Writer writer; + + private PlainTextWriter indentedWriter; + + private IndentedPlainTextWriter(final PlainTextWriter plainTextWriter, final Writer writer) { + this.plainTextWriter = plainTextWriter; + this.writer = writer; + } + + @Override + public void println(final String format, final Object... args) throws IOException { + writer.write(spaces); + plainTextWriter.println(format, args); + } + + @Override + public PlainTextWriter indentedWriter() { + if (indentedWriter == null) { + indentedWriter = new IndentedPlainTextWriter(this, writer); + } + return indentedWriter; + } + } +} diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java index c3bede8b..6e9e1a94 100644 --- a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java @@ -6,6 +6,8 @@ import org.asamk.signal.manager.groups.GroupUtils; import org.asamk.signal.manager.storage.groups.GroupInfo; import org.asamk.signal.util.DateUtils; import org.asamk.signal.util.Util; +import org.slf4j.helpers.MessageFormatter; +import org.whispersystems.libsignal.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceContent; @@ -38,8 +40,10 @@ import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import java.io.File; +import java.io.IOException; import java.util.Base64; import java.util.List; +import java.util.stream.Collectors; public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { @@ -51,606 +55,644 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { @Override public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) { - if (!envelope.isUnidentifiedSender() && envelope.hasSource()) { + try { + printMessage(envelope, content, exception); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void printMessage( + SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception + ) throws IOException { + PlainTextWriter writer = new PlainTextWriterImpl(System.out); + + if (envelope.hasSource()) { SignalServiceAddress source = envelope.getSourceAddress(); - String name = m.getContactOrProfileName(source.getLegacyIdentifier()); - System.out.println(String.format("Envelope from: %s (device: %d)", - (name == null ? "" : "“" + name + "” ") + source.getLegacyIdentifier(), - envelope.getSourceDevice())); + writer.println("Envelope from: {} (device: {})", formatContact(source), envelope.getSourceDevice()); if (source.getRelay().isPresent()) { - System.out.println("Relayed by: " + source.getRelay().get()); + writer.println("Relayed by: {}", source.getRelay().get()); } } else { - System.out.println("Envelope from: unknown source"); + writer.println("Envelope from: unknown source"); } - System.out.println("Timestamp: " + DateUtils.formatTimestamp(envelope.getTimestamp())); + writer.println("Timestamp: {}", DateUtils.formatTimestamp(envelope.getTimestamp())); if (envelope.isUnidentifiedSender()) { - System.out.println("Sent by unidentified/sealed sender"); + writer.println("Sent by unidentified/sealed sender"); } if (envelope.isReceipt()) { - System.out.println("Got receipt."); + writer.println("Got receipt."); } else if (envelope.isSignalMessage() || envelope.isPreKeySignalMessage() || envelope.isUnidentifiedSender()) { if (exception != null) { - if (exception instanceof org.whispersystems.libsignal.UntrustedIdentityException) { - org.whispersystems.libsignal.UntrustedIdentityException e = (org.whispersystems.libsignal.UntrustedIdentityException) exception; - System.out.println( + if (exception instanceof UntrustedIdentityException) { + UntrustedIdentityException e = (UntrustedIdentityException) exception; + writer.println( "The user’s key is untrusted, either the user has reinstalled Signal or a third party sent this message."); - System.out.println("Use 'signal-cli -u " - + m.getUsername() - + " listIdentities -n " - + e.getName() - + "', verify the key and run 'signal-cli -u " - + m.getUsername() - + " trust -v \"FINGER_PRINT\" " - + e.getName() - + "' to mark it as trusted"); - System.out.println("If you don't care about security, use 'signal-cli -u " - + m.getUsername() - + " trust -a " - + e.getName() - + "' to trust it without verification"); + writer.println( + "Use 'signal-cli -u {0} listIdentities -n {1}', verify the key and run 'signal-cli -u {0} trust -v \"FINGER_PRINT\" {1}' to mark it as trusted", + m.getUsername(), + e.getName()); + writer.println( + "If you don't care about security, use 'signal-cli -u {} trust -a {}' to trust it without verification", + m.getUsername(), + e.getName()); } else { - System.out.println("Exception: " + exception.getMessage() + " (" + exception.getClass() - .getSimpleName() + ")"); + writer.println("Exception: {} ({})", exception.getMessage(), exception.getClass().getSimpleName()); } } if (content == null) { - System.out.println("Failed to decrypt message."); + writer.println("Failed to decrypt message."); } else { - String senderName = m.getContactOrProfileName(content.getSender().getLegacyIdentifier()); - System.out.println(String.format("Sender: %s (device: %d)", - (senderName == null ? "" : "“" + senderName + "” ") + content.getSender().getLegacyIdentifier(), - content.getSenderDevice())); + writer.println("Sender: {} (device: {})", + formatContact(content.getSender()), + content.getSenderDevice()); + writer.println("Server timestamps: received: {} delivered: {}", + DateUtils.formatTimestamp(content.getServerReceivedTimestamp()), + DateUtils.formatTimestamp(content.getServerDeliveredTimestamp())); + if (content.getDataMessage().isPresent()) { SignalServiceDataMessage message = content.getDataMessage().get(); - handleSignalServiceDataMessage(message); + printDataMessage(writer, message); } if (content.getSyncMessage().isPresent()) { - System.out.println("Received a sync message"); + writer.println("Received a sync message"); SignalServiceSyncMessage syncMessage = content.getSyncMessage().get(); - - if (syncMessage.getContacts().isPresent()) { - final ContactsMessage contactsMessage = syncMessage.getContacts().get(); - if (contactsMessage.isComplete()) { - System.out.println("Received complete sync contacts"); - } else { - System.out.println("Received sync contacts"); - } - printAttachment(contactsMessage.getContactsStream(), 0); - } - if (syncMessage.getGroups().isPresent()) { - System.out.println("Received sync groups"); - printAttachment(syncMessage.getGroups().get(), 0); - } - if (syncMessage.getRead().isPresent()) { - System.out.println("Received sync read messages list"); - for (ReadMessage rm : syncMessage.getRead().get()) { - String name = m.getContactOrProfileName(rm.getSender().getLegacyIdentifier()); - System.out.println("From: " - + (name == null ? "" : "“" + name + "” ") - + rm.getSender() - .getLegacyIdentifier() - + " Message timestamp: " - + DateUtils.formatTimestamp(rm.getTimestamp())); - } - } - if (syncMessage.getRequest().isPresent()) { - System.out.println("Received sync request"); - if (syncMessage.getRequest().get().isContactsRequest()) { - System.out.println(" - contacts request"); - } - if (syncMessage.getRequest().get().isGroupsRequest()) { - System.out.println(" - groups request"); - } - if (syncMessage.getRequest().get().isBlockedListRequest()) { - System.out.println(" - blocked list request"); - } - if (syncMessage.getRequest().get().isConfigurationRequest()) { - System.out.println(" - configuration request"); - } - if (syncMessage.getRequest().get().isKeysRequest()) { - System.out.println(" - keys request"); - } - } - if (syncMessage.getSent().isPresent()) { - System.out.println("Received sync sent message"); - final SentTranscriptMessage sentTranscriptMessage = syncMessage.getSent().get(); - String to; - if (sentTranscriptMessage.getDestination().isPresent()) { - String dest = sentTranscriptMessage.getDestination().get().getLegacyIdentifier(); - String name = m.getContactOrProfileName(dest); - to = (name == null ? "" : "“" + name + "” ") + dest; - } else if (sentTranscriptMessage.getRecipients().size() > 0) { - StringBuilder toBuilder = new StringBuilder(); - for (SignalServiceAddress dest : sentTranscriptMessage.getRecipients()) { - String name = m.getContactOrProfileName(dest.getLegacyIdentifier()); - toBuilder.append(name == null ? "" : "“" + name + "” ") - .append(dest.getLegacyIdentifier()) - .append(" "); - } - to = toBuilder.toString(); - } else { - to = "Unknown"; - } - System.out.println("To: " + to + " , Message timestamp: " + DateUtils.formatTimestamp( - sentTranscriptMessage.getTimestamp())); - if (sentTranscriptMessage.getExpirationStartTimestamp() > 0) { - System.out.println("Expiration started at: " + DateUtils.formatTimestamp( - sentTranscriptMessage.getExpirationStartTimestamp())); - } - SignalServiceDataMessage message = sentTranscriptMessage.getMessage(); - handleSignalServiceDataMessage(message); - } - if (syncMessage.getBlockedList().isPresent()) { - System.out.println("Received sync message with block list"); - System.out.println("Blocked numbers:"); - final BlockedListMessage blockedList = syncMessage.getBlockedList().get(); - for (SignalServiceAddress address : blockedList.getAddresses()) { - System.out.println(" - " + address.getLegacyIdentifier()); - } - } - if (syncMessage.getVerified().isPresent()) { - System.out.println("Received sync message with verified identities:"); - final VerifiedMessage verifiedMessage = syncMessage.getVerified().get(); - System.out.println(" - " - + verifiedMessage.getDestination() - + ": " - + verifiedMessage.getVerified()); - String safetyNumber = Util.formatSafetyNumber(m.computeSafetyNumber(verifiedMessage.getDestination(), - verifiedMessage.getIdentityKey())); - System.out.println(" " + safetyNumber); - } - if (syncMessage.getConfiguration().isPresent()) { - System.out.println("Received sync message with configuration:"); - final ConfigurationMessage configurationMessage = syncMessage.getConfiguration().get(); - if (configurationMessage.getReadReceipts().isPresent()) { - System.out.println(" - Read receipts: " + ( - configurationMessage.getReadReceipts().get() ? "enabled" : "disabled" - )); - } - if (configurationMessage.getLinkPreviews().isPresent()) { - System.out.println(" - Link previews: " + ( - configurationMessage.getLinkPreviews().get() ? "enabled" : "disabled" - )); - } - if (configurationMessage.getTypingIndicators().isPresent()) { - System.out.println(" - Typing indicators: " + ( - configurationMessage.getTypingIndicators().get() ? "enabled" : "disabled" - )); - } - if (configurationMessage.getUnidentifiedDeliveryIndicators().isPresent()) { - System.out.println(" - Unidentified Delivery Indicators: " + ( - configurationMessage.getUnidentifiedDeliveryIndicators().get() - ? "enabled" - : "disabled" - )); - } - } - if (syncMessage.getFetchType().isPresent()) { - final SignalServiceSyncMessage.FetchType fetchType = syncMessage.getFetchType().get(); - System.out.println("Received sync message with fetch type: " + fetchType.toString()); - } - if (syncMessage.getViewOnceOpen().isPresent()) { - final ViewOnceOpenMessage viewOnceOpenMessage = syncMessage.getViewOnceOpen().get(); - System.out.println("Received sync message with view once open message:"); - System.out.println(" - Sender:" + viewOnceOpenMessage.getSender().getLegacyIdentifier()); - System.out.println(" - Timestamp:" + viewOnceOpenMessage.getTimestamp()); - } - if (syncMessage.getStickerPackOperations().isPresent()) { - final List stickerPackOperationMessages = syncMessage.getStickerPackOperations() - .get(); - System.out.println("Received sync message with sticker pack operations:"); - for (StickerPackOperationMessage m : stickerPackOperationMessages) { - System.out.println(" - " + m.getType().toString()); - if (m.getPackId().isPresent()) { - System.out.println(" packId: " + Base64.getEncoder() - .encodeToString(m.getPackId().get())); - } - if (m.getPackKey().isPresent()) { - System.out.println(" packKey: " + Base64.getEncoder() - .encodeToString(m.getPackKey().get())); - } - } - } - if (syncMessage.getMessageRequestResponse().isPresent()) { - final MessageRequestResponseMessage requestResponseMessage = syncMessage.getMessageRequestResponse() - .get(); - System.out.println("Received message request response:"); - System.out.println(" Type: " + requestResponseMessage.getType()); - if (requestResponseMessage.getGroupId().isPresent()) { - System.out.println(" Group id: " + Base64.getEncoder() - .encodeToString(requestResponseMessage.getGroupId().get())); - } - if (requestResponseMessage.getPerson().isPresent()) { - System.out.println(" Person: " + requestResponseMessage.getPerson() - .get() - .getLegacyIdentifier()); - } - } - if (syncMessage.getKeys().isPresent()) { - final KeysMessage keysMessage = syncMessage.getKeys().get(); - System.out.println("Received sync message with keys:"); - if (keysMessage.getStorageService().isPresent()) { - System.out.println(" With storage key length: " + keysMessage.getStorageService() - .get() - .serialize().length); - } else { - System.out.println(" With empty storage key"); - } - } + printSyncMessage(writer, syncMessage); } + if (content.getCallMessage().isPresent()) { - System.out.println("Received a call message"); + writer.println("Received a call message"); SignalServiceCallMessage callMessage = content.getCallMessage().get(); - if (callMessage.getDestinationDeviceId().isPresent()) { - final Integer deviceId = callMessage.getDestinationDeviceId().get(); - System.out.println("Destination device id: " + deviceId); - } - if (callMessage.getAnswerMessage().isPresent()) { - AnswerMessage answerMessage = callMessage.getAnswerMessage().get(); - System.out.println("Answer message: " + answerMessage.getId() + ": " + answerMessage.getSdp()); - } - if (callMessage.getBusyMessage().isPresent()) { - BusyMessage busyMessage = callMessage.getBusyMessage().get(); - System.out.println("Busy message: " + busyMessage.getId()); - } - if (callMessage.getHangupMessage().isPresent()) { - HangupMessage hangupMessage = callMessage.getHangupMessage().get(); - System.out.println("Hangup message: " + hangupMessage.getId()); - } - if (callMessage.getIceUpdateMessages().isPresent()) { - List iceUpdateMessages = callMessage.getIceUpdateMessages().get(); - for (IceUpdateMessage iceUpdateMessage : iceUpdateMessages) { - System.out.println("Ice update message: " - + iceUpdateMessage.getId() - + ", sdp: " - + iceUpdateMessage.getSdp()); - } - } - if (callMessage.getOfferMessage().isPresent()) { - OfferMessage offerMessage = callMessage.getOfferMessage().get(); - System.out.println("Offer message: " + offerMessage.getId() + ": " + offerMessage.getSdp()); - } - if (callMessage.getOpaqueMessage().isPresent()) { - final OpaqueMessage opaqueMessage = callMessage.getOpaqueMessage().get(); - System.out.println("Opaque message: size " + opaqueMessage.getOpaque().length); - } + printCallMessage(writer.indentedWriter(), callMessage); } if (content.getReceiptMessage().isPresent()) { - System.out.println("Received a receipt message"); + writer.println("Received a receipt message"); SignalServiceReceiptMessage receiptMessage = content.getReceiptMessage().get(); - System.out.println(" - When: " + DateUtils.formatTimestamp(receiptMessage.getWhen())); - if (receiptMessage.isDeliveryReceipt()) { - System.out.println(" - Is delivery receipt"); - } - if (receiptMessage.isReadReceipt()) { - System.out.println(" - Is read receipt"); - } - if (receiptMessage.isViewedReceipt()) { - System.out.println(" - Is viewed receipt"); - } - System.out.println(" - Timestamps:"); - for (long timestamp : receiptMessage.getTimestamps()) { - System.out.println(" " + DateUtils.formatTimestamp(timestamp)); - } + printReceiptMessage(writer.indentedWriter(), receiptMessage); } if (content.getTypingMessage().isPresent()) { - System.out.println("Received a typing message"); + writer.println("Received a typing message"); SignalServiceTypingMessage typingMessage = content.getTypingMessage().get(); - System.out.println(" - Action: " + typingMessage.getAction()); - System.out.println(" - Timestamp: " + DateUtils.formatTimestamp(typingMessage.getTimestamp())); - if (typingMessage.getGroupId().isPresent()) { - System.out.println(" - Group Info:"); - final GroupId groupId = GroupId.unknownVersion(typingMessage.getGroupId().get()); - System.out.println(" Id: " + groupId.toBase64()); - GroupInfo group = m.getGroup(groupId); - if (group != null) { - System.out.println(" Name: " + group.getTitle()); - } else { - System.out.println(" Name: "); - } - } + printTypingMessage(writer.indentedWriter(), typingMessage); } } } else { - System.out.println("Unknown message received."); + writer.println("Unknown message received."); } - System.out.println(); + writer.println(); } - private void handleSignalServiceDataMessage(SignalServiceDataMessage message) { - System.out.println("Message timestamp: " + DateUtils.formatTimestamp(message.getTimestamp())); + private void printDataMessage( + PlainTextWriter writer, SignalServiceDataMessage message + ) throws IOException { + writer.println("Message timestamp: {}", DateUtils.formatTimestamp(message.getTimestamp())); if (message.isViewOnce()) { - System.out.println("=VIEW ONCE="); + writer.println("=VIEW ONCE="); } if (message.getBody().isPresent()) { - System.out.println("Body: " + message.getBody().get()); + writer.println("Body: {}", message.getBody().get()); } if (message.getGroupContext().isPresent()) { - System.out.println("Group info:"); + writer.println("Group info:"); final SignalServiceGroupContext groupContext = message.getGroupContext().get(); - final GroupId groupId = GroupUtils.getGroupId(groupContext); - if (groupContext.getGroupV1().isPresent()) { - SignalServiceGroup groupInfo = groupContext.getGroupV1().get(); - System.out.println(" Id: " + groupId.toBase64()); - if (groupInfo.getType() == SignalServiceGroup.Type.UPDATE && groupInfo.getName().isPresent()) { - System.out.println(" Name: " + groupInfo.getName().get()); - } else { - GroupInfo group = m.getGroup(groupId); - if (group != null) { - System.out.println(" Name: " + group.getTitle()); - } else { - System.out.println(" Name: "); - } - } - System.out.println(" Type: " + groupInfo.getType()); - if (groupInfo.getMembers().isPresent()) { - for (SignalServiceAddress member : groupInfo.getMembers().get()) { - System.out.println(" Member: " + member.getLegacyIdentifier()); - } - } - if (groupInfo.getAvatar().isPresent()) { - System.out.println(" Avatar:"); - printAttachment(groupInfo.getAvatar().get(), 2); - } - } else if (groupContext.getGroupV2().isPresent()) { - final SignalServiceGroupV2 groupInfo = groupContext.getGroupV2().get(); - System.out.println(" Id: " + groupId.toBase64()); - GroupInfo group = m.getGroup(groupId); - if (group != null) { - System.out.println(" Name: " + group.getTitle()); - } else { - System.out.println(" Name: "); - } - System.out.println(" Revision: " + groupInfo.getRevision()); - System.out.println(" Master key length: " + groupInfo.getMasterKey().serialize().length); - System.out.println(" Has signed group change: " + groupInfo.hasSignedGroupChange()); - } + printGroupContext(writer.indentedWriter(), groupContext); } if (message.getGroupCallUpdate().isPresent()) { + writer.println("Group call update:"); final SignalServiceDataMessage.GroupCallUpdate groupCallUpdate = message.getGroupCallUpdate().get(); - System.out.println("Group call update:"); - System.out.println(" - Era id: " + groupCallUpdate.getEraId()); + writer.indentedWriter().println("Era id: {}", groupCallUpdate.getEraId()); } if (message.getPreviews().isPresent()) { + writer.println("Previews:"); final List previews = message.getPreviews().get(); - System.out.println("Previews:"); for (SignalServiceDataMessage.Preview preview : previews) { - System.out.println(" - Title: " + preview.getTitle()); - System.out.println(" - Url: " + preview.getUrl()); - if (preview.getImage().isPresent()) { - printAttachment(preview.getImage().get(), 1); - } + writer.println("- Preview"); + printPreview(writer.indentedWriter(), preview); } } if (message.getSharedContacts().isPresent()) { final List sharedContacts = message.getSharedContacts().get(); - System.out.println("Contacts:"); + writer.println("Contacts:"); for (SharedContact contact : sharedContacts) { - System.out.println(" - Name:"); - SharedContact.Name name = contact.getName(); - if (name.getDisplay().isPresent() && !name.getDisplay().get().isBlank()) { - System.out.println(" - Display name: " + name.getDisplay().get()); - } - if (name.getGiven().isPresent() && !name.getGiven().get().isBlank()) { - System.out.println(" - First name: " + name.getGiven().get()); - } - if (name.getMiddle().isPresent() && !name.getMiddle().get().isBlank()) { - System.out.println(" - Middle name: " + name.getMiddle().get()); - } - if (name.getFamily().isPresent() && !name.getFamily().get().isBlank()) { - System.out.println(" - Family name: " + name.getFamily().get()); - } - if (name.getPrefix().isPresent() && !name.getPrefix().get().isBlank()) { - System.out.println(" - Prefix name: " + name.getPrefix().get()); - } - if (name.getSuffix().isPresent() && !name.getSuffix().get().isBlank()) { - System.out.println(" - Suffix name: " + name.getSuffix().get()); - } - - if (contact.getAvatar().isPresent()) { - SharedContact.Avatar avatar = contact.getAvatar().get(); - System.out.println(" - Avatar:"); - printAttachment(avatar.getAttachment(), 3); - if (avatar.isProfile()) { - System.out.println(" - Is profile"); - } else { - System.out.println(" - Is not a profile"); - } - } - - if (contact.getPhone().isPresent()) { - System.out.println(" - Phone details:"); - for (SharedContact.Phone phone : contact.getPhone().get()) { - System.out.println(" - Phone:"); - if (phone.getValue() != null) { - System.out.println(" - Number: " + phone.getValue()); - } - if (phone.getType() != null) { - System.out.println(" - Type: " + phone.getType()); - } - if (phone.getLabel().isPresent() && !phone.getLabel().get().isBlank()) { - System.out.println(" - Label: " + phone.getLabel().get()); - } - } - } - - if (contact.getEmail().isPresent()) { - System.out.println(" - Email details:"); - for (SharedContact.Email email : contact.getEmail().get()) { - System.out.println(" - Email:"); - if (email.getValue() != null) { - System.out.println(" - Value: " + email.getValue()); - } - if (email.getType() != null) { - System.out.println(" - Type: " + email.getType()); - } - if (email.getLabel().isPresent() && !email.getLabel().get().isBlank()) { - System.out.println(" - Label: " + email.getLabel().get()); - } - } - } - - if (contact.getAddress().isPresent()) { - System.out.println(" - Address details:"); - for (SharedContact.PostalAddress address : contact.getAddress().get()) { - System.out.println(" - Address:"); - if (address.getType() != null) { - System.out.println(" - Type: " + address.getType()); - } - if (address.getLabel().isPresent() && !address.getLabel().get().isBlank()) { - System.out.println(" - Label: " + address.getLabel().get()); - } - if (address.getStreet().isPresent() && !address.getStreet().get().isBlank()) { - System.out.println(" - Street: " + address.getStreet().get()); - } - if (address.getPobox().isPresent() && !address.getPobox().get().isBlank()) { - System.out.println(" - Pobox: " + address.getPobox().get()); - } - if (address.getNeighborhood().isPresent() && !address.getNeighborhood().get().isBlank()) { - System.out.println(" - Neighbourhood: " + address.getNeighborhood().get()); - } - if (address.getCity().isPresent() && !address.getCity().get().isBlank()) { - System.out.println(" - City: " + address.getCity().get()); - } - if (address.getRegion().isPresent() && !address.getRegion().get().isBlank()) { - System.out.println(" - Region: " + address.getRegion().get()); - } - if (address.getPostcode().isPresent() && !address.getPostcode().get().isBlank()) { - System.out.println(" - Postcode: " + address.getPostcode().get()); - } - if (address.getCountry().isPresent() && !address.getCountry().get().isBlank()) { - System.out.println(" - Country: " + address.getCountry().get()); - } - } - } - - System.out.println(" - Organisation: " + ( - contact.getOrganization().isPresent() ? contact.getOrganization().get() : "-" - )); + writer.println("- Contact:"); + printSharedContact(writer.indentedWriter(), contact); } } if (message.getSticker().isPresent()) { final SignalServiceDataMessage.Sticker sticker = message.getSticker().get(); - System.out.println("Sticker:"); - System.out.println(" - Pack id: " + Base64.getEncoder().encodeToString(sticker.getPackId())); - System.out.println(" - Pack key: " + Base64.getEncoder().encodeToString(sticker.getPackKey())); - System.out.println(" - Sticker id: " + sticker.getStickerId()); - // TODO also download sticker image ?? + writer.println("Sticker:"); + printSticker(writer.indentedWriter(), sticker); } if (message.isEndSession()) { - System.out.println("Is end session"); + writer.println("Is end session"); } if (message.isExpirationUpdate()) { - System.out.println("Is Expiration update: " + message.isExpirationUpdate()); + writer.println("Is Expiration update: {}", message.isExpirationUpdate()); } if (message.getExpiresInSeconds() > 0) { - System.out.println("Expires in: " + message.getExpiresInSeconds() + " seconds"); + writer.println("Expires in: {} seconds", message.getExpiresInSeconds()); } if (message.getProfileKey().isPresent()) { - System.out.println("Profile key update, key length:" + message.getProfileKey().get().length); + writer.println("Profile key update, key length: {}", message.getProfileKey().get().length); } - if (message.getReaction().isPresent()) { + writer.println("Reaction:"); final SignalServiceDataMessage.Reaction reaction = message.getReaction().get(); - System.out.println("Reaction:"); - System.out.println(" - Emoji: " + reaction.getEmoji()); - System.out.println(" - Target author: " + m.resolveSignalServiceAddress(reaction.getTargetAuthor()) - .getLegacyIdentifier()); - System.out.println(" - Target timestamp: " + reaction.getTargetSentTimestamp()); - System.out.println(" - Is remove: " + reaction.isRemove()); + printReaction(writer.indentedWriter(), reaction); } - if (message.getQuote().isPresent()) { + writer.println("Quote:"); SignalServiceDataMessage.Quote quote = message.getQuote().get(); - System.out.println("Quote: (" + quote.getId() + ")"); - System.out.println(" Author: " + m.resolveSignalServiceAddress(quote.getAuthor()).getLegacyIdentifier()); - System.out.println(" Text: " + quote.getText()); - if (quote.getMentions() != null && quote.getMentions().size() > 0) { - System.out.println(" Mentions: "); - for (SignalServiceDataMessage.Mention mention : quote.getMentions()) { - printMention(mention, m, 1); + printQuote(writer.indentedWriter(), quote); + } + if (message.getRemoteDelete().isPresent()) { + final SignalServiceDataMessage.RemoteDelete remoteDelete = message.getRemoteDelete().get(); + writer.println("Remote delete message: timestamp = {}", remoteDelete.getTargetSentTimestamp()); + } + if (message.getMentions().isPresent()) { + writer.println("Mentions:"); + for (SignalServiceDataMessage.Mention mention : message.getMentions().get()) { + printMention(writer, mention); + } + } + if (message.getAttachments().isPresent()) { + writer.println("Attachments:"); + for (SignalServiceAttachment attachment : message.getAttachments().get()) { + writer.println("- Attachment:"); + printAttachment(writer.indentedWriter(), attachment); + } + } + } + + private void printTypingMessage( + final PlainTextWriter writer, final SignalServiceTypingMessage typingMessage + ) throws IOException { + writer.println("Action: {}", typingMessage.getAction()); + writer.println("Timestamp: {}", DateUtils.formatTimestamp(typingMessage.getTimestamp())); + if (typingMessage.getGroupId().isPresent()) { + writer.println("Group Info:"); + final GroupId groupId = GroupId.unknownVersion(typingMessage.getGroupId().get()); + printGroupInfo(writer.indentedWriter(), groupId); + } + } + + private void printReceiptMessage( + final PlainTextWriter writer, final SignalServiceReceiptMessage receiptMessage + ) throws IOException { + writer.println("When: {}", DateUtils.formatTimestamp(receiptMessage.getWhen())); + if (receiptMessage.isDeliveryReceipt()) { + writer.println("Is delivery receipt"); + } + if (receiptMessage.isReadReceipt()) { + writer.println("Is read receipt"); + } + if (receiptMessage.isViewedReceipt()) { + writer.println("Is viewed receipt"); + } + writer.println("Timestamps:"); + for (long timestamp : receiptMessage.getTimestamps()) { + writer.println("- {}", DateUtils.formatTimestamp(timestamp)); + } + } + + private void printCallMessage( + final PlainTextWriter writer, final SignalServiceCallMessage callMessage + ) throws IOException { + if (callMessage.getDestinationDeviceId().isPresent()) { + final Integer deviceId = callMessage.getDestinationDeviceId().get(); + writer.println("Destination device id: {}", deviceId); + } + if (callMessage.getAnswerMessage().isPresent()) { + AnswerMessage answerMessage = callMessage.getAnswerMessage().get(); + writer.println("Answer message: {}, sdp: {})", answerMessage.getId(), answerMessage.getSdp()); + } + if (callMessage.getBusyMessage().isPresent()) { + BusyMessage busyMessage = callMessage.getBusyMessage().get(); + writer.println("Busy message: {}", busyMessage.getId()); + } + if (callMessage.getHangupMessage().isPresent()) { + HangupMessage hangupMessage = callMessage.getHangupMessage().get(); + writer.println("Hangup message: {}", hangupMessage.getId()); + } + if (callMessage.getIceUpdateMessages().isPresent()) { + writer.println("Ice update messages:"); + List iceUpdateMessages = callMessage.getIceUpdateMessages().get(); + for (IceUpdateMessage iceUpdateMessage : iceUpdateMessages) { + writer.println("- {}, sdp: {}", iceUpdateMessage.getId(), iceUpdateMessage.getSdp()); + } + } + if (callMessage.getOfferMessage().isPresent()) { + OfferMessage offerMessage = callMessage.getOfferMessage().get(); + writer.println("Offer message: {}, sdp: {}", offerMessage.getId(), offerMessage.getSdp()); + } + if (callMessage.getOpaqueMessage().isPresent()) { + final OpaqueMessage opaqueMessage = callMessage.getOpaqueMessage().get(); + writer.println("Opaque message: size {}", opaqueMessage.getOpaque().length); + } + } + + private void printSyncMessage( + final PlainTextWriter writer, final SignalServiceSyncMessage syncMessage + ) throws IOException { + if (syncMessage.getContacts().isPresent()) { + final ContactsMessage contactsMessage = syncMessage.getContacts().get(); + String type = contactsMessage.isComplete() ? "complete" : "partial"; + writer.println("Received {} sync contacts:", type); + printAttachment(writer.indentedWriter(), contactsMessage.getContactsStream()); + } + if (syncMessage.getGroups().isPresent()) { + writer.println("Received sync groups:"); + printAttachment(writer.indentedWriter(), syncMessage.getGroups().get()); + } + if (syncMessage.getRead().isPresent()) { + writer.println("Received sync read messages list"); + for (ReadMessage rm : syncMessage.getRead().get()) { + writer.println("- From: {} Message timestamp: {}", + formatContact(rm.getSender()), + DateUtils.formatTimestamp(rm.getTimestamp())); + } + } + if (syncMessage.getRequest().isPresent()) { + String type; + if (syncMessage.getRequest().get().isContactsRequest()) { + type = "contacts"; + } else if (syncMessage.getRequest().get().isGroupsRequest()) { + type = "groups"; + } else if (syncMessage.getRequest().get().isBlockedListRequest()) { + type = "blocked list"; + } else if (syncMessage.getRequest().get().isConfigurationRequest()) { + type = "configuration"; + } else if (syncMessage.getRequest().get().isKeysRequest()) { + type = "keys"; + } else { + type = ""; + } + writer.println("Received sync request for: {}", type); + } + if (syncMessage.getSent().isPresent()) { + writer.println("Received sync sent message"); + final SentTranscriptMessage sentTranscriptMessage = syncMessage.getSent().get(); + String to; + if (sentTranscriptMessage.getDestination().isPresent()) { + to = formatContact(sentTranscriptMessage.getDestination().get()); + } else if (sentTranscriptMessage.getRecipients().size() > 0) { + to = sentTranscriptMessage.getRecipients() + .stream() + .map(this::formatContact) + .collect(Collectors.joining(", ")); + } else { + to = ""; + } + writer.indentedWriter().println("To: {}", to); + writer.indentedWriter() + .println("Timestamp: {}", DateUtils.formatTimestamp(sentTranscriptMessage.getTimestamp())); + if (sentTranscriptMessage.getExpirationStartTimestamp() > 0) { + writer.indentedWriter() + .println("Expiration started at: {}", + DateUtils.formatTimestamp(sentTranscriptMessage.getExpirationStartTimestamp())); + } + SignalServiceDataMessage message = sentTranscriptMessage.getMessage(); + printDataMessage(writer.indentedWriter(), message); + } + if (syncMessage.getBlockedList().isPresent()) { + writer.println("Received sync message with block list"); + writer.println("Blocked numbers:"); + final BlockedListMessage blockedList = syncMessage.getBlockedList().get(); + for (SignalServiceAddress address : blockedList.getAddresses()) { + writer.println("- {}", address.getLegacyIdentifier()); + } + } + if (syncMessage.getVerified().isPresent()) { + writer.println("Received sync message with verified identities:"); + final VerifiedMessage verifiedMessage = syncMessage.getVerified().get(); + writer.println("- {}: {}", formatContact(verifiedMessage.getDestination()), verifiedMessage.getVerified()); + String safetyNumber = Util.formatSafetyNumber(m.computeSafetyNumber(verifiedMessage.getDestination(), + verifiedMessage.getIdentityKey())); + writer.indentedWriter().println(safetyNumber); + } + if (syncMessage.getConfiguration().isPresent()) { + writer.println("Received sync message with configuration:"); + final ConfigurationMessage configurationMessage = syncMessage.getConfiguration().get(); + if (configurationMessage.getReadReceipts().isPresent()) { + writer.println("- Read receipts: {}", + configurationMessage.getReadReceipts().get() ? "enabled" : "disabled"); + } + if (configurationMessage.getLinkPreviews().isPresent()) { + writer.println("- Link previews: {}", + configurationMessage.getLinkPreviews().get() ? "enabled" : "disabled"); + } + if (configurationMessage.getTypingIndicators().isPresent()) { + writer.println("- Typing indicators: {}", + configurationMessage.getTypingIndicators().get() ? "enabled" : "disabled"); + } + if (configurationMessage.getUnidentifiedDeliveryIndicators().isPresent()) { + writer.println("- Unidentified Delivery Indicators: {}", + configurationMessage.getUnidentifiedDeliveryIndicators().get() ? "enabled" : "disabled"); + } + } + if (syncMessage.getFetchType().isPresent()) { + final SignalServiceSyncMessage.FetchType fetchType = syncMessage.getFetchType().get(); + writer.println("Received sync message with fetch type: {}", fetchType); + } + if (syncMessage.getViewOnceOpen().isPresent()) { + final ViewOnceOpenMessage viewOnceOpenMessage = syncMessage.getViewOnceOpen().get(); + writer.println("Received sync message with view once open message:"); + writer.indentedWriter().println("Sender: {}", formatContact(viewOnceOpenMessage.getSender())); + writer.indentedWriter() + .println("Timestamp: {}", DateUtils.formatTimestamp(viewOnceOpenMessage.getTimestamp())); + } + if (syncMessage.getStickerPackOperations().isPresent()) { + final List stickerPackOperationMessages = syncMessage.getStickerPackOperations() + .get(); + writer.println("Received sync message with sticker pack operations:"); + for (StickerPackOperationMessage m : stickerPackOperationMessages) { + writer.println("- {}", m.getType().isPresent() ? m.getType().get() : ""); + if (m.getPackId().isPresent()) { + writer.indentedWriter() + .println("packId: {}", Base64.getEncoder().encodeToString(m.getPackId().get())); + } + if (m.getPackKey().isPresent()) { + writer.indentedWriter() + .println("packKey: {}", Base64.getEncoder().encodeToString(m.getPackKey().get())); } } - if (quote.getAttachments().size() > 0) { - System.out.println(" Attachments: "); - for (SignalServiceDataMessage.Quote.QuotedAttachment attachment : quote.getAttachments()) { - System.out.println(" - Filename: " + attachment.getFileName()); - System.out.println(" Type: " + attachment.getContentType()); - System.out.println(" Thumbnail:"); + } + if (syncMessage.getMessageRequestResponse().isPresent()) { + final MessageRequestResponseMessage requestResponseMessage = syncMessage.getMessageRequestResponse().get(); + writer.println("Received message request response:"); + writer.indentedWriter().println("Type: {}", requestResponseMessage.getType()); + if (requestResponseMessage.getGroupId().isPresent()) { + writer.println("For group:"); + printGroupInfo(writer.indentedWriter(), + GroupId.unknownVersion(requestResponseMessage.getGroupId().get())); + } + if (requestResponseMessage.getPerson().isPresent()) { + writer.indentedWriter() + .println("For Person: {}", formatContact(requestResponseMessage.getPerson().get())); + } + } + if (syncMessage.getKeys().isPresent()) { + final KeysMessage keysMessage = syncMessage.getKeys().get(); + writer.println("Received sync message with keys:"); + if (keysMessage.getStorageService().isPresent()) { + writer.println("- storage key: length: {}", keysMessage.getStorageService().get().serialize().length); + } + } + } + + private void printPreview( + final PlainTextWriter writer, final SignalServiceDataMessage.Preview preview + ) throws IOException { + writer.println("Title: {}", preview.getTitle()); + writer.println("Description: {}", preview.getDescription()); + writer.println("Date: {}", DateUtils.formatTimestamp(preview.getDate())); + writer.println("Url: {}", preview.getUrl()); + if (preview.getImage().isPresent()) { + writer.println("Image:"); + printAttachment(writer.indentedWriter(), preview.getImage().get()); + } + } + + private void printSticker( + final PlainTextWriter writer, final SignalServiceDataMessage.Sticker sticker + ) throws IOException { + writer.println("Pack id: {}", Base64.getEncoder().encodeToString(sticker.getPackId())); + writer.println("Pack key: {}", Base64.getEncoder().encodeToString(sticker.getPackKey())); + writer.println("Sticker id: {}", sticker.getStickerId()); + writer.println("Image:"); + printAttachment(writer.indentedWriter(), sticker.getAttachment()); + } + + private void printReaction( + final PlainTextWriter writer, final SignalServiceDataMessage.Reaction reaction + ) throws IOException { + writer.println("Emoji: {}", reaction.getEmoji()); + writer.println("Target author: {}", formatContact(m.resolveSignalServiceAddress(reaction.getTargetAuthor()))); + writer.println("Target timestamp: {}", DateUtils.formatTimestamp(reaction.getTargetSentTimestamp())); + writer.println("Is remove: {}", reaction.isRemove()); + } + + private void printQuote( + final PlainTextWriter writer, final SignalServiceDataMessage.Quote quote + ) throws IOException { + writer.println("Id: {}", quote.getId()); + writer.println("Author: {}", m.resolveSignalServiceAddress(quote.getAuthor()).getLegacyIdentifier()); + writer.println("Text: {}", quote.getText()); + if (quote.getMentions() != null && quote.getMentions().size() > 0) { + writer.println("Mentions:"); + for (SignalServiceDataMessage.Mention mention : quote.getMentions()) { + printMention(writer, mention); + } + } + if (quote.getAttachments().size() > 0) { + writer.println("Attachments:"); + for (SignalServiceDataMessage.Quote.QuotedAttachment attachment : quote.getAttachments()) { + writer.println("- Filename: {}", attachment.getFileName()); + writer.indent(w -> { + w.println("Type: {}", attachment.getContentType()); + w.println("Thumbnail:"); if (attachment.getThumbnail() != null) { - printAttachment(attachment.getThumbnail(), 3); + printAttachment(w, attachment.getThumbnail()); } - } + }); } } + } - if (message.getRemoteDelete().isPresent()) { - final SignalServiceDataMessage.RemoteDelete remoteDelete = message.getRemoteDelete().get(); - System.out.println("Remote delete message: timestamp = " + remoteDelete.getTargetSentTimestamp()); + private void printSharedContact(final PlainTextWriter writer, final SharedContact contact) throws IOException { + writer.println("Name:"); + SharedContact.Name name = contact.getName(); + writer.indent(w -> { + if (name.getDisplay().isPresent() && !name.getDisplay().get().isBlank()) { + w.println("Display name: {}", name.getDisplay().get()); + } + if (name.getGiven().isPresent() && !name.getGiven().get().isBlank()) { + w.println("First name: {}", name.getGiven().get()); + } + if (name.getMiddle().isPresent() && !name.getMiddle().get().isBlank()) { + w.println("Middle name: {}", name.getMiddle().get()); + } + if (name.getFamily().isPresent() && !name.getFamily().get().isBlank()) { + w.println("Family name: {}", name.getFamily().get()); + } + if (name.getPrefix().isPresent() && !name.getPrefix().get().isBlank()) { + w.println("Prefix name: {}", name.getPrefix().get()); + } + if (name.getSuffix().isPresent() && !name.getSuffix().get().isBlank()) { + w.println("Suffix name: {}", name.getSuffix().get()); + } + }); + + if (contact.getAvatar().isPresent()) { + SharedContact.Avatar avatar = contact.getAvatar().get(); + writer.println("Avatar: (profile: {})", avatar.isProfile()); + printAttachment(writer.indentedWriter(), avatar.getAttachment()); } - if (message.getMentions().isPresent()) { - System.out.println("Mentions: "); - for (SignalServiceDataMessage.Mention mention : message.getMentions().get()) { - printMention(mention, m, 0); + + if (contact.getOrganization().isPresent()) { + writer.println("Organisation: {}", contact.getOrganization().get()); + } + + if (contact.getPhone().isPresent()) { + writer.println("Phone details:"); + for (SharedContact.Phone phone : contact.getPhone().get()) { + writer.println("- Phone:"); + writer.indent(w -> { + if (phone.getValue() != null) { + w.println("Number: {}", phone.getValue()); + } + if (phone.getType() != null) { + w.println("Type: {}", phone.getType()); + } + if (phone.getLabel().isPresent() && !phone.getLabel().get().isBlank()) { + w.println("Label: {}", phone.getLabel().get()); + } + }); } } - if (message.getAttachments().isPresent()) { - System.out.println("Attachments: "); - for (SignalServiceAttachment attachment : message.getAttachments().get()) { - printAttachment(attachment, 0); + if (contact.getEmail().isPresent()) { + writer.println("Email details:"); + for (SharedContact.Email email : contact.getEmail().get()) { + writer.println("- Email:"); + writer.indent(w -> { + if (email.getValue() != null) { + w.println("Address: {}", email.getValue()); + } + if (email.getType() != null) { + w.println("Type: {}", email.getType()); + } + if (email.getLabel().isPresent() && !email.getLabel().get().isBlank()) { + w.println("Label: {}", email.getLabel().get()); + } + }); + } + } + + if (contact.getAddress().isPresent()) { + writer.println("Address details:"); + for (SharedContact.PostalAddress address : contact.getAddress().get()) { + writer.println("- Address:"); + writer.indent(w -> { + if (address.getType() != null) { + w.println("Type: {}", address.getType()); + } + if (address.getLabel().isPresent() && !address.getLabel().get().isBlank()) { + w.println("Label: {}", address.getLabel().get()); + } + if (address.getStreet().isPresent() && !address.getStreet().get().isBlank()) { + w.println("Street: {}", address.getStreet().get()); + } + if (address.getPobox().isPresent() && !address.getPobox().get().isBlank()) { + w.println("Pobox: {}", address.getPobox().get()); + } + if (address.getNeighborhood().isPresent() && !address.getNeighborhood().get().isBlank()) { + w.println("Neighbourhood: {}", address.getNeighborhood().get()); + } + if (address.getCity().isPresent() && !address.getCity().get().isBlank()) { + w.println("City: {}", address.getCity().get()); + } + if (address.getRegion().isPresent() && !address.getRegion().get().isBlank()) { + w.println("Region: {}", address.getRegion().get()); + } + if (address.getPostcode().isPresent() && !address.getPostcode().get().isBlank()) { + w.println("Postcode: {}", address.getPostcode().get()); + } + if (address.getCountry().isPresent() && !address.getCountry().get().isBlank()) { + w.println("Country: {}", address.getCountry().get()); + } + }); } } } - /** - * Prints the Signal mention information - * - * @param mention is the Signal mention to print - * @param m is the Manager. used to resolve UUIDs into phone numbers if possible - * @param leadingSpaces is the number of spaces you want the message to be indented by - */ - private void printMention(SignalServiceDataMessage.Mention mention, Manager m, int leadingSpaces) { - String spaces = " ".repeat(leadingSpaces); - System.out.println(spaces + "- " + m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), - null)).getLegacyIdentifier() + ": " + mention.getStart() + " (length: " + mention.getLength() + ")"); + private void printGroupContext( + final PlainTextWriter writer, final SignalServiceGroupContext groupContext + ) throws IOException { + final GroupId groupId = GroupUtils.getGroupId(groupContext); + if (groupContext.getGroupV1().isPresent()) { + SignalServiceGroup groupInfo = groupContext.getGroupV1().get(); + printGroupInfo(writer, groupId); + writer.println("Type: {}", groupInfo.getType()); + if (groupInfo.getMembers().isPresent()) { + writer.println("Members:"); + for (SignalServiceAddress member : groupInfo.getMembers().get()) { + writer.println("- {}", formatContact(member)); + } + } + if (groupInfo.getAvatar().isPresent()) { + writer.println("Avatar:"); + printAttachment(writer.indentedWriter(), groupInfo.getAvatar().get()); + } + } else if (groupContext.getGroupV2().isPresent()) { + final SignalServiceGroupV2 groupInfo = groupContext.getGroupV2().get(); + printGroupInfo(writer, groupId); + writer.println("Revision: {}", groupInfo.getRevision()); + writer.println("Master key length: {}", groupInfo.getMasterKey().serialize().length); + writer.println("Has signed group change: {}", groupInfo.hasSignedGroupChange()); + } } - /** - * Prints the Signal attachment information - * - * @param attachment is the Signal attachment to print - * @param leadingSpaces is the number of spaces you want the message to be indented by - */ - private void printAttachment(SignalServiceAttachment attachment, int leadingSpaces) { - String spaces = " ".repeat(leadingSpaces); - System.out.println(spaces + "- " + attachment.getContentType() + " (" + ( - attachment.isPointer() ? "Pointer" : "" - ) + ( - attachment.isStream() ? "Stream" : "" - ) + ")"); + private void printGroupInfo(final PlainTextWriter writer, final GroupId groupId) throws IOException { + writer.println("Id: {}", groupId.toBase64()); + + GroupInfo group = m.getGroup(groupId); + if (group != null) { + writer.println("Name: {}", group.getTitle()); + } else { + writer.println("Name: "); + } + } + + private void printMention( + PlainTextWriter writer, SignalServiceDataMessage.Mention mention + ) throws IOException { + final SignalServiceAddress address = m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), + null)); + writer.println("- {}: {} (length: {})", formatContact(address), mention.getStart(), mention.getLength()); + } + + private void printAttachment(PlainTextWriter writer, SignalServiceAttachment attachment) throws IOException { + writer.println("Content-Type: {}", attachment.getContentType()); + writer.println("Type: {}", attachment.isPointer() ? "Pointer" : attachment.isStream() ? "Stream" : ""); if (attachment.isPointer()) { final SignalServiceAttachmentPointer pointer = attachment.asPointer(); - System.out.println(spaces + " Id: " + pointer.getRemoteId() + " Key length: " + pointer.getKey().length); - System.out.println(spaces + " Filename: " + ( - pointer.getFileName().isPresent() ? pointer.getFileName().get() : "-" - )); - System.out.println(spaces + " Size: " + ( - pointer.getSize().isPresent() ? pointer.getSize().get() + " bytes" : "" - ) + ( + writer.println("Id: {} Key length: {}", pointer.getRemoteId(), pointer.getKey().length); + if (pointer.getUploadTimestamp() > 0) { + writer.println("Upload timestamp: {}", DateUtils.formatTimestamp(pointer.getUploadTimestamp())); + } + if (pointer.getCaption().isPresent()) { + writer.println("Caption: {}", pointer.getCaption().get()); + } + if (pointer.getFileName().isPresent()) { + writer.println("Filename: {}", pointer.getFileName().get()); + } + writer.println("Size: {}{}", + pointer.getSize().isPresent() ? pointer.getSize().get() + " bytes" : "", pointer.getPreview().isPresent() ? " (Preview is available: " + pointer.getPreview().get().length - + " bytes)" : "" - )); - System.out.println(spaces + " Voice note: " + (pointer.getVoiceNote() ? "yes" : "no")); - System.out.println(spaces + " Dimensions: " + pointer.getWidth() + "x" + pointer.getHeight()); + + " bytes)" : ""); + writer.println("Voice note: {}", pointer.getVoiceNote() ? "yes" : "no"); + writer.println("Borderless: {}", pointer.isBorderless() ? "yes" : "no"); + if (pointer.getWidth() > 0 || pointer.getHeight() > 0) { + writer.println("Dimensions: {}x{}", pointer.getWidth(), pointer.getHeight()); + } File file = m.getAttachmentFile(pointer.getRemoteId()); if (file.exists()) { - System.out.println(spaces + " Stored plaintext in: " + file); + writer.println("Stored plaintext in: {}", file); } } } + + private String formatContact(SignalServiceAddress address) { + final String number = address.getLegacyIdentifier(); + String name = m.getContactOrProfileName(number); + if (name == null) { + return number; + } else { + return MessageFormatter.arrayFormat("“{}” {}", new Object[]{name, number}).getMessage(); + } + } } diff --git a/src/main/java/org/asamk/signal/util/DateUtils.java b/src/main/java/org/asamk/signal/util/DateUtils.java index c9b92529..f94261bf 100644 --- a/src/main/java/org/asamk/signal/util/DateUtils.java +++ b/src/main/java/org/asamk/signal/util/DateUtils.java @@ -14,7 +14,7 @@ public class DateUtils { public static String formatTimestamp(long timestamp) { Date date = new Date(timestamp); - final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); // Quoted "Z" to indicate UTC, no timezone offset + final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"); // Quoted "Z" to indicate UTC, no timezone offset df.setTimeZone(tzUTC); return timestamp + " (" + df.format(date) + ")"; } -- 2.51.0 From de273586b4106171a3940ce5ec2c2b3712430c8c Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 21 Feb 2021 15:01:41 +0100 Subject: [PATCH 05/16] Use var instead of explicit types --- .../org/asamk/signal/manager/AvatarStore.java | 2 +- .../asamk/signal/manager/DeviceLinkInfo.java | 24 +- .../asamk/signal/manager/HandleAction.java | 10 +- .../asamk/signal/manager/LibSignalLogger.java | 2 +- .../org/asamk/signal/manager/Manager.java | 566 ++++++++---------- .../signal/manager/ProvisioningManager.java | 23 +- .../signal/manager/RegistrationManager.java | 28 +- .../signal/manager/config/ServiceConfig.java | 4 +- .../asamk/signal/manager/groups/GroupId.java | 2 +- .../manager/groups/GroupInviteLinkUrl.java | 20 +- .../signal/manager/groups/GroupUtils.java | 11 +- .../signal/manager/helper/GroupHelper.java | 122 ++-- .../signal/manager/helper/PinHelper.java | 20 +- .../signal/manager/helper/ProfileHelper.java | 20 +- .../helper/UnidentifiedAccessHelper.java | 16 +- .../signal/manager/storage/SignalAccount.java | 73 +-- .../storage/contacts/JsonContactsStore.java | 6 +- .../manager/storage/groups/GroupInfo.java | 4 +- .../manager/storage/groups/GroupInfoV1.java | 10 +- .../storage/groups/JsonGroupStore.java | 36 +- .../storage/messageCache/MessageCache.java | 10 +- .../storage/profiles/ProfileStore.java | 35 +- .../protocol/JsonIdentityKeyStore.java | 49 +- .../storage/protocol/JsonPreKeyStore.java | 12 +- .../storage/protocol/JsonSessionStore.java | 49 +- .../protocol/JsonSignedPreKeyStore.java | 16 +- .../storage/protocol/RecipientStore.java | 15 +- .../storage/stickers/StickerStore.java | 15 +- .../threads/LegacyJsonThreadStore.java | 6 +- .../signal/manager/util/AttachmentUtils.java | 6 +- .../asamk/signal/manager/util/IOUtils.java | 11 +- .../asamk/signal/manager/util/KeyUtils.java | 24 +- .../manager/util/MessageCacheUtils.java | 24 +- .../asamk/signal/manager/util/PinHashing.java | 6 +- .../signal/manager/util/ProfileUtils.java | 8 +- .../signal/manager/util/StickerUtils.java | 19 +- .../org/asamk/signal/manager/util/Utils.java | 11 +- src/main/java/org/asamk/signal/App.java | 50 +- .../signal/JsonDbusReceiveMessageHandler.java | 25 +- .../signal/JsonReceiveMessageHandler.java | 3 +- src/main/java/org/asamk/signal/Main.java | 9 +- .../org/asamk/signal/PlainTextWriterImpl.java | 2 +- .../asamk/signal/ReceiveMessageHandler.java | 146 ++--- .../asamk/signal/commands/BlockCommand.java | 7 +- .../asamk/signal/commands/DaemonCommand.java | 24 +- .../signal/commands/GetUserStatusCommand.java | 9 +- .../signal/commands/JoinGroupCommand.java | 10 +- .../asamk/signal/commands/LinkCommand.java | 4 +- .../signal/commands/ListContactsCommand.java | 7 +- .../signal/commands/ListDevicesCommand.java | 6 +- .../signal/commands/ListGroupsCommand.java | 14 +- .../commands/ListIdentitiesCommand.java | 12 +- .../signal/commands/QuitGroupCommand.java | 8 +- .../asamk/signal/commands/ReceiveCommand.java | 28 +- .../signal/commands/RegisterCommand.java | 2 +- .../asamk/signal/commands/SendCommand.java | 19 +- .../signal/commands/SendReactionCommand.java | 11 +- .../asamk/signal/commands/SetPinCommand.java | 2 +- .../asamk/signal/commands/TrustCommand.java | 9 +- .../asamk/signal/commands/UnblockCommand.java | 7 +- .../signal/commands/UpdateContactCommand.java | 6 +- .../signal/commands/UpdateGroupCommand.java | 6 +- .../signal/commands/UpdateProfileCommand.java | 11 +- .../commands/UploadStickerPackCommand.java | 4 +- .../asamk/signal/commands/VerifyCommand.java | 4 +- .../org/asamk/signal/dbus/DbusSignalImpl.java | 41 +- .../org/asamk/signal/json/JsonAttachment.java | 6 +- .../asamk/signal/json/JsonDataMessage.java | 9 +- .../signal/json/JsonMessageEnvelope.java | 3 +- .../asamk/signal/json/JsonSyncMessage.java | 2 +- .../asamk/signal/json/JsonTypingMessage.java | 2 +- .../java/org/asamk/signal/util/DateUtils.java | 2 +- .../org/asamk/signal/util/ErrorUtils.java | 10 +- src/main/java/org/asamk/signal/util/Hex.java | 14 +- .../java/org/asamk/signal/util/IOUtils.java | 6 +- .../org/asamk/signal/util/RandomUtils.java | 2 +- src/main/java/org/asamk/signal/util/Util.java | 10 +- 77 files changed, 850 insertions(+), 1017 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/AvatarStore.java b/lib/src/main/java/org/asamk/signal/manager/AvatarStore.java index 712e982c..de59f2af 100644 --- a/lib/src/main/java/org/asamk/signal/manager/AvatarStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/AvatarStore.java @@ -29,7 +29,7 @@ public class AvatarStore { } public StreamDetails retrieveGroupAvatar(GroupId groupId) throws IOException { - final File groupAvatarFile = getGroupAvatarFile(groupId); + final var groupAvatarFile = getGroupAvatarFile(groupId); return retrieveAvatar(groupAvatarFile); } diff --git a/lib/src/main/java/org/asamk/signal/manager/DeviceLinkInfo.java b/lib/src/main/java/org/asamk/signal/manager/DeviceLinkInfo.java index b8b27eaa..82d8a37f 100644 --- a/lib/src/main/java/org/asamk/signal/manager/DeviceLinkInfo.java +++ b/lib/src/main/java/org/asamk/signal/manager/DeviceLinkInfo.java @@ -20,14 +20,14 @@ public class DeviceLinkInfo { final ECPublicKey deviceKey; public static DeviceLinkInfo parseDeviceLinkUri(URI linkUri) throws InvalidKeyException { - final String rawQuery = linkUri.getRawQuery(); + final var rawQuery = linkUri.getRawQuery(); if (isEmpty(rawQuery)) { throw new RuntimeException("Invalid device link uri"); } - Map query = getQueryMap(rawQuery); - String deviceIdentifier = query.get("uuid"); - String publicKeyEncoded = query.get("pub_key"); + var query = getQueryMap(rawQuery); + var deviceIdentifier = query.get("uuid"); + var publicKeyEncoded = query.get("pub_key"); if (isEmpty(deviceIdentifier) || isEmpty(publicKeyEncoded)) { throw new RuntimeException("Invalid device link uri"); @@ -39,18 +39,18 @@ public class DeviceLinkInfo { } catch (IllegalArgumentException e) { throw new RuntimeException("Invalid device link uri", e); } - ECPublicKey deviceKey = Curve.decodePoint(publicKeyBytes, 0); + var deviceKey = Curve.decodePoint(publicKeyBytes, 0); return new DeviceLinkInfo(deviceIdentifier, deviceKey); } private static Map getQueryMap(String query) { - String[] params = query.split("&"); - Map map = new HashMap<>(); - for (String param : params) { - final String[] paramParts = param.split("="); - String name = URLDecoder.decode(paramParts[0], StandardCharsets.UTF_8); - String value = URLDecoder.decode(paramParts[1], StandardCharsets.UTF_8); + var params = query.split("&"); + var map = new HashMap(); + for (var param : params) { + final var paramParts = param.split("="); + var name = URLDecoder.decode(paramParts[0], StandardCharsets.UTF_8); + var value = URLDecoder.decode(paramParts[1], StandardCharsets.UTF_8); map.put(name, value); } return map; @@ -62,7 +62,7 @@ public class DeviceLinkInfo { } public String createDeviceLinkUri() { - final String deviceKeyString = Base64.getEncoder().encodeToString(deviceKey.serialize()).replace("=", ""); + final var deviceKeyString = Base64.getEncoder().encodeToString(deviceKey.serialize()).replace("=", ""); return "tsdevice:/?uuid=" + URLEncoder.encode(deviceIdentifier, StandardCharsets.UTF_8) + "&pub_key=" diff --git a/lib/src/main/java/org/asamk/signal/manager/HandleAction.java b/lib/src/main/java/org/asamk/signal/manager/HandleAction.java index 8338e4e6..9d119c11 100644 --- a/lib/src/main/java/org/asamk/signal/manager/HandleAction.java +++ b/lib/src/main/java/org/asamk/signal/manager/HandleAction.java @@ -29,7 +29,7 @@ class SendReceiptAction implements HandleAction { public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final SendReceiptAction that = (SendReceiptAction) o; + final var that = (SendReceiptAction) o; return timestamp == that.timestamp && address.equals(that.address); } @@ -110,7 +110,7 @@ class SendGroupInfoRequestAction implements HandleAction { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final SendGroupInfoRequestAction that = (SendGroupInfoRequestAction) o; + final var that = (SendGroupInfoRequestAction) o; if (!address.equals(that.address)) return false; return groupId.equals(that.groupId); @@ -118,7 +118,7 @@ class SendGroupInfoRequestAction implements HandleAction { @Override public int hashCode() { - int result = address.hashCode(); + var result = address.hashCode(); result = 31 * result + groupId.hashCode(); return result; } @@ -144,7 +144,7 @@ class SendGroupInfoAction implements HandleAction { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final SendGroupInfoAction that = (SendGroupInfoAction) o; + final var that = (SendGroupInfoAction) o; if (!address.equals(that.address)) return false; return groupId.equals(that.groupId); @@ -152,7 +152,7 @@ class SendGroupInfoAction implements HandleAction { @Override public int hashCode() { - int result = address.hashCode(); + var result = address.hashCode(); result = 31 * result + groupId.hashCode(); return result; } diff --git a/lib/src/main/java/org/asamk/signal/manager/LibSignalLogger.java b/lib/src/main/java/org/asamk/signal/manager/LibSignalLogger.java index 9118846d..3be4d7e9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/LibSignalLogger.java +++ b/lib/src/main/java/org/asamk/signal/manager/LibSignalLogger.java @@ -18,7 +18,7 @@ public class LibSignalLogger implements SignalProtocolLogger { @Override public void log(final int priority, final String tag, final String message) { - final String logMessage = String.format("[%s]: %s", tag, message); + final var logMessage = String.format("[%s]: %s", tag, message); switch (priority) { case SignalProtocolLogger.VERBOSE: logger.trace(logMessage); diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index 80ff4e71..caedf2f1 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -21,7 +21,6 @@ import org.asamk.signal.manager.config.ServiceEnvironment; import org.asamk.signal.manager.config.ServiceEnvironmentConfig; import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupIdV1; -import org.asamk.signal.manager.groups.GroupIdV2; import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.GroupUtils; @@ -37,7 +36,6 @@ import org.asamk.signal.manager.storage.groups.GroupInfoV1; import org.asamk.signal.manager.storage.groups.GroupInfoV2; import org.asamk.signal.manager.storage.messageCache.CachedMessage; import org.asamk.signal.manager.storage.profiles.SignalProfile; -import org.asamk.signal.manager.storage.profiles.SignalProfileEntry; import org.asamk.signal.manager.storage.protocol.IdentityInfo; import org.asamk.signal.manager.storage.stickers.Sticker; import org.asamk.signal.manager.util.AttachmentUtils; @@ -60,11 +58,8 @@ import org.signal.libsignal.metadata.SelfSendException; import org.signal.libsignal.metadata.certificate.CertificateValidator; import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.protos.groups.local.DecryptedGroup; -import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; -import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.zkgroup.InvalidInputException; import org.signal.zkgroup.VerificationFailedException; -import org.signal.zkgroup.auth.AuthCredentialResponse; import org.signal.zkgroup.groups.GroupMasterKey; import org.signal.zkgroup.groups.GroupSecretParams; import org.signal.zkgroup.profiles.ClientZkProfileOperations; @@ -81,20 +76,17 @@ import org.whispersystems.libsignal.state.PreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.KeyBackupService; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceMessagePipe; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.SignalServiceCipher; -import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations; import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api; import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString; import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; -import org.whispersystems.signalservice.api.kbs.MasterKey; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; @@ -106,7 +98,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; import org.whispersystems.signalservice.api.messages.SignalServiceGroup; import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; -import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifestUpload; import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage; import org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage; import org.whispersystems.signalservice.api.messages.multidevice.DeviceContact; @@ -116,22 +107,18 @@ import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroup; import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsInputStream; import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsOutputStream; import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo; -import org.whispersystems.signalservice.api.messages.multidevice.KeysMessage; import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage; import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage; import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage; import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage; -import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException; -import org.whispersystems.signalservice.api.storage.StorageKey; import org.whispersystems.signalservice.api.util.InvalidNumberException; import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import org.whispersystems.signalservice.api.util.SleepTimer; -import org.whispersystems.signalservice.api.util.StreamDetails; import org.whispersystems.signalservice.api.util.UptimeSleepTimer; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.contacts.crypto.Quote; @@ -160,7 +147,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -225,7 +211,7 @@ public class Manager implements Closeable { ServiceConfig.AUTOMATIC_NETWORK_RETRY, timer); this.groupsV2Api = accountManager.getGroupsV2Api(); - final KeyBackupService keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(), + final var keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(), serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(), serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(), serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(), @@ -286,29 +272,27 @@ public class Manager implements Closeable { public static Manager init( String username, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent ) throws IOException, NotRegisteredException { - PathConfig pathConfig = PathConfig.createDefault(settingsPath); + var pathConfig = PathConfig.createDefault(settingsPath); if (!SignalAccount.userExists(pathConfig.getDataPath(), username)) { throw new NotRegisteredException(); } - SignalAccount account = SignalAccount.load(pathConfig.getDataPath(), username); + var account = SignalAccount.load(pathConfig.getDataPath(), username); if (!account.isRegistered()) { throw new NotRegisteredException(); } - final ServiceEnvironmentConfig serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig( - serviceEnvironment, - userAgent); + final var serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent); return new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent); } public static List getAllLocalUsernames(File settingsPath) { - PathConfig pathConfig = PathConfig.createDefault(settingsPath); - final File dataPath = pathConfig.getDataPath(); - final File[] files = dataPath.listFiles(); + var pathConfig = PathConfig.createDefault(settingsPath); + final var dataPath = pathConfig.getDataPath(); + final var files = dataPath.listFiles(); if (files == null) { return List.of(); @@ -342,9 +326,9 @@ public class Manager implements Closeable { */ public Map areUsersRegistered(Set numbers) throws IOException { // Note "contactDetails" has no optionals. It only gives us info on users who are registered - Map contactDetails = getRegisteredUsers(numbers); + var contactDetails = getRegisteredUsers(numbers); - Set registeredUsers = contactDetails.keySet(); + var registeredUsers = contactDetails.keySet(); return numbers.stream().collect(Collectors.toMap(x -> x, registeredUsers::contains)); } @@ -370,9 +354,9 @@ public class Manager implements Closeable { * if it's Optional.absent(), the avatar will be removed */ public void setProfile(String name, String about, String aboutEmoji, Optional avatar) throws IOException { - SignalProfileEntry profileEntry = account.getProfileStore().getProfileEntry(getSelfAddress()); - SignalProfile profile = profileEntry == null ? null : profileEntry.getProfile(); - SignalProfile newProfile = new SignalProfile(profile == null ? null : profile.getIdentityKey(), + var profileEntry = account.getProfileStore().getProfileEntry(getSelfAddress()); + var profile = profileEntry == null ? null : profileEntry.getProfile(); + var newProfile = new SignalProfile(profile == null ? null : profile.getIdentityKey(), name != null ? name : profile == null || profile.getName() == null ? "" : profile.getName(), about != null ? about : profile == null || profile.getAbout() == null ? "" : profile.getAbout(), aboutEmoji != null @@ -382,7 +366,7 @@ public class Manager implements Closeable { account.isUnrestrictedUnidentifiedAccess(), profile == null ? null : profile.getCapabilities()); - try (final StreamDetails streamDetails = avatar == null + try (final var streamDetails = avatar == null ? avatarStore.retrieveProfileAvatar(getSelfAddress()) : avatar.isPresent() ? Utils.createStreamDetailsFromFile(avatar.get()) : null) { accountManager.setVersionedProfile(account.getUuid(), @@ -426,7 +410,7 @@ public class Manager implements Closeable { } public List getLinkedDevices() throws IOException { - List devices = accountManager.getDevices(); + var devices = accountManager.getDevices(); account.setMultiDevice(devices.size() > 1); account.save(); return devices; @@ -434,20 +418,20 @@ public class Manager implements Closeable { public void removeLinkedDevices(int deviceId) throws IOException { accountManager.removeDevice(deviceId); - List devices = accountManager.getDevices(); + var devices = accountManager.getDevices(); account.setMultiDevice(devices.size() > 1); account.save(); } public void addDeviceLink(URI linkUri) throws IOException, InvalidKeyException { - DeviceLinkInfo info = DeviceLinkInfo.parseDeviceLinkUri(linkUri); + var info = DeviceLinkInfo.parseDeviceLinkUri(linkUri); addDevice(info.deviceIdentifier, info.deviceKey); } private void addDevice(String deviceIdentifier, ECPublicKey deviceKey) throws IOException, InvalidKeyException { - IdentityKeyPair identityKeyPair = getIdentityKeyPair(); - String verificationCode = accountManager.getNewDeviceVerificationCode(); + var identityKeyPair = getIdentityKeyPair(); + var verificationCode = accountManager.getNewDeviceVerificationCode(); accountManager.addDevice(deviceIdentifier, deviceKey, @@ -463,7 +447,7 @@ public class Manager implements Closeable { throw new RuntimeException("Only master device can set a PIN"); } if (pin.isPresent()) { - final MasterKey masterKey = account.getPinMasterKey() != null + final var masterKey = account.getPinMasterKey() != null ? account.getPinMasterKey() : KeyUtils.createMasterKey(); @@ -485,17 +469,17 @@ public class Manager implements Closeable { } void refreshPreKeys() throws IOException { - List oneTimePreKeys = generatePreKeys(); - final IdentityKeyPair identityKeyPair = getIdentityKeyPair(); - SignedPreKeyRecord signedPreKeyRecord = generateSignedPreKey(identityKeyPair); + var oneTimePreKeys = generatePreKeys(); + final var identityKeyPair = getIdentityKeyPair(); + var signedPreKeyRecord = generateSignedPreKey(identityKeyPair); accountManager.setPreKeys(identityKeyPair.getPublicKey(), signedPreKeyRecord, oneTimePreKeys); } private List generatePreKeys() { - final int offset = account.getPreKeyIdOffset(); + final var offset = account.getPreKeyIdOffset(); - List records = KeyUtils.generatePreKeyRecords(offset, ServiceConfig.PREKEY_BATCH_SIZE); + var records = KeyUtils.generatePreKeyRecords(offset, ServiceConfig.PREKEY_BATCH_SIZE); account.addPreKeys(records); account.save(); @@ -503,9 +487,9 @@ public class Manager implements Closeable { } private SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityKeyPair) { - final int signedPreKeyId = account.getNextSignedPreKeyId(); + final var signedPreKeyId = account.getNextSignedPreKeyId(); - SignedPreKeyRecord record = KeyUtils.generateSignedPreKeyRecord(identityKeyPair, signedPreKeyId); + var record = KeyUtils.generateSignedPreKeyRecord(identityKeyPair, signedPreKeyId); account.addSignedPreKey(record); account.save(); @@ -553,11 +537,11 @@ public class Manager implements Closeable { private SignalProfile getRecipientProfile( SignalServiceAddress address, boolean force ) { - SignalProfileEntry profileEntry = account.getProfileStore().getProfileEntry(address); + var profileEntry = account.getProfileStore().getProfileEntry(address); if (profileEntry == null) { return null; } - long now = new Date().getTime(); + var now = new Date().getTime(); // Profiles are cached for 24h before retrieving them again if (!profileEntry.isRequestPending() && ( force @@ -576,8 +560,8 @@ public class Manager implements Closeable { profileEntry.setRequestPending(false); } - final ProfileKey profileKey = profileEntry.getProfileKey(); - final SignalProfile profile = decryptProfileAndDownloadAvatar(address, profileKey, encryptedProfile); + final var profileKey = profileEntry.getProfileKey(); + final var profile = decryptProfileAndDownloadAvatar(address, profileKey, encryptedProfile); account.getProfileStore() .updateProfile(address, profileKey, now, profile, profileEntry.getProfileKeyCredential()); return profile; @@ -586,7 +570,7 @@ public class Manager implements Closeable { } private ProfileKeyCredential getRecipientProfileKeyCredential(SignalServiceAddress address) { - SignalProfileEntry profileEntry = account.getProfileStore().getProfileEntry(address); + var profileEntry = account.getProfileStore().getProfileEntry(address); if (profileEntry == null) { return null; } @@ -600,9 +584,9 @@ public class Manager implements Closeable { return null; } - long now = new Date().getTime(); - final ProfileKeyCredential profileKeyCredential = profileAndCredential.getProfileKeyCredential().orNull(); - final SignalProfile profile = decryptProfileAndDownloadAvatar(address, + var now = new Date().getTime(); + final var profileKeyCredential = profileAndCredential.getProfileKeyCredential().orNull(); + final var profile = decryptProfileAndDownloadAvatar(address, profileEntry.getProfileKey(), profileAndCredential.getProfile()); account.getProfileStore() @@ -623,7 +607,7 @@ public class Manager implements Closeable { } private Optional createGroupAvatarAttachment(GroupId groupId) throws IOException { - final StreamDetails streamDetails = avatarStore.retrieveGroupAvatar(groupId); + final var streamDetails = avatarStore.retrieveGroupAvatar(groupId); if (streamDetails == null) { return Optional.absent(); } @@ -632,7 +616,7 @@ public class Manager implements Closeable { } private Optional createContactAvatarAttachment(SignalServiceAddress address) throws IOException { - final StreamDetails streamDetails = avatarStore.retrieveContactAvatar(address); + final var streamDetails = avatarStore.retrieveContactAvatar(address); if (streamDetails == null) { return Optional.absent(); } @@ -641,7 +625,7 @@ public class Manager implements Closeable { } private GroupInfo getGroupForSending(GroupId groupId) throws GroupNotFoundException, NotAGroupMemberException { - GroupInfo g = getGroup(groupId); + var g = getGroup(groupId); if (g == null) { throw new GroupNotFoundException(groupId); } @@ -652,7 +636,7 @@ public class Manager implements Closeable { } private GroupInfo getGroupForUpdating(GroupId groupId) throws GroupNotFoundException, NotAGroupMemberException { - GroupInfo g = getGroup(groupId); + var g = getGroup(groupId); if (g == null) { throw new GroupNotFoundException(groupId); } @@ -669,8 +653,7 @@ public class Manager implements Closeable { public Pair> sendGroupMessage( String messageText, List attachments, GroupId groupId ) throws IOException, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException { - final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() - .withBody(messageText); + final var messageBuilder = SignalServiceDataMessage.newBuilder().withBody(messageText); if (attachments != null) { messageBuilder.withAttachments(AttachmentUtils.getSignalServiceAttachments(attachments)); } @@ -681,12 +664,11 @@ public class Manager implements Closeable { public Pair> sendGroupMessageReaction( String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, GroupId groupId ) throws IOException, InvalidNumberException, NotAGroupMemberException, GroupNotFoundException { - SignalServiceDataMessage.Reaction reaction = new SignalServiceDataMessage.Reaction(emoji, + var reaction = new SignalServiceDataMessage.Reaction(emoji, remove, canonicalizeAndResolveSignalServiceAddress(targetAuthor), targetSentTimestamp); - final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() - .withReaction(reaction); + final var messageBuilder = SignalServiceDataMessage.newBuilder().withReaction(reaction); return sendGroupMessage(messageBuilder, groupId); } @@ -694,7 +676,7 @@ public class Manager implements Closeable { public Pair> sendGroupMessage( SignalServiceDataMessage.Builder messageBuilder, GroupId groupId ) throws IOException, GroupNotFoundException, NotAGroupMemberException { - final GroupInfo g = getGroupForSending(groupId); + final var g = getGroupForSending(groupId); GroupUtils.setGroupContext(messageBuilder, g); messageBuilder.withExpiration(g.getMessageExpirationTime()); @@ -705,18 +687,16 @@ public class Manager implements Closeable { public Pair> sendQuitGroupMessage(GroupId groupId) throws GroupNotFoundException, IOException, NotAGroupMemberException { SignalServiceDataMessage.Builder messageBuilder; - final GroupInfo g = getGroupForUpdating(groupId); + final var g = getGroupForUpdating(groupId); if (g instanceof GroupInfoV1) { - GroupInfoV1 groupInfoV1 = (GroupInfoV1) g; - SignalServiceGroup group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.QUIT) - .withId(groupId.serialize()) - .build(); + var groupInfoV1 = (GroupInfoV1) g; + var group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.QUIT).withId(groupId.serialize()).build(); messageBuilder = SignalServiceDataMessage.newBuilder().asGroupMessage(group); groupInfoV1.removeMember(account.getSelfAddress()); account.getGroupStore().updateGroup(groupInfoV1); } else { - final GroupInfoV2 groupInfoV2 = (GroupInfoV2) g; - final Pair groupGroupChangePair = groupHelper.leaveGroup(groupInfoV2); + final var groupInfoV2 = (GroupInfoV2) g; + final var groupGroupChangePair = groupHelper.leaveGroup(groupInfoV2); groupInfoV2.setGroup(groupGroupChangePair.first()); messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2, groupGroupChangePair.second().toByteArray()); account.getGroupStore().updateGroup(groupInfoV2); @@ -741,11 +721,11 @@ public class Manager implements Closeable { SignalServiceDataMessage.Builder messageBuilder; if (groupId == null) { // Create new group - GroupInfoV2 gv2 = groupHelper.createGroupV2(name == null ? "" : name, + var gv2 = groupHelper.createGroupV2(name == null ? "" : name, members == null ? List.of() : members, avatarFile); if (gv2 == null) { - GroupInfoV1 gv1 = new GroupInfoV1(GroupIdV1.createRandom()); + var gv1 = new GroupInfoV1(GroupIdV1.createRandom()); gv1.addMembers(List.of(account.getSelfAddress())); updateGroupV1(gv1, name, members, avatarFile); messageBuilder = getGroupUpdateMessageBuilder(gv1); @@ -759,36 +739,33 @@ public class Manager implements Closeable { g = gv2; } } else { - GroupInfo group = getGroupForUpdating(groupId); + var group = getGroupForUpdating(groupId); if (group instanceof GroupInfoV2) { - final GroupInfoV2 groupInfoV2 = (GroupInfoV2) group; + final var groupInfoV2 = (GroupInfoV2) group; Pair> result = null; if (groupInfoV2.isPendingMember(getSelfAddress())) { - Pair groupGroupChangePair = groupHelper.acceptInvite(groupInfoV2); + var groupGroupChangePair = groupHelper.acceptInvite(groupInfoV2); result = sendUpdateGroupMessage(groupInfoV2, groupGroupChangePair.first(), groupGroupChangePair.second()); } if (members != null) { - final Set newMembers = new HashSet<>(members); + final var newMembers = new HashSet<>(members); newMembers.removeAll(group.getMembers() .stream() .map(this::resolveSignalServiceAddress) .collect(Collectors.toSet())); if (newMembers.size() > 0) { - Pair groupGroupChangePair = groupHelper.updateGroupV2(groupInfoV2, - newMembers); + var groupGroupChangePair = groupHelper.updateGroupV2(groupInfoV2, newMembers); result = sendUpdateGroupMessage(groupInfoV2, groupGroupChangePair.first(), groupGroupChangePair.second()); } } if (result == null || name != null || avatarFile != null) { - Pair groupGroupChangePair = groupHelper.updateGroupV2(groupInfoV2, - name, - avatarFile); + var groupGroupChangePair = groupHelper.updateGroupV2(groupInfoV2, name, avatarFile); if (avatarFile != null) { avatarStore.storeGroupAvatar(groupInfoV2.getGroupId(), outputStream -> IOUtils.copyFileToStream(avatarFile, outputStream)); @@ -800,7 +777,7 @@ public class Manager implements Closeable { return new Pair<>(group.getGroupId(), result.second()); } else { - GroupInfoV1 gv1 = (GroupInfoV1) group; + var gv1 = (GroupInfoV1) group; updateGroupV1(gv1, name, members, avatarFile); messageBuilder = getGroupUpdateMessageBuilder(gv1); g = gv1; @@ -809,8 +786,7 @@ public class Manager implements Closeable { account.getGroupStore().updateGroup(g); - final Pair> result = sendMessage(messageBuilder, - g.getMembersIncludingPendingWithout(account.getSelfAddress())); + final var result = sendMessage(messageBuilder, g.getMembersIncludingPendingWithout(account.getSelfAddress())); return new Pair<>(g.getGroupId(), result.second()); } @@ -825,15 +801,15 @@ public class Manager implements Closeable { } if (members != null) { - final Set newE164Members = new HashSet<>(); - for (SignalServiceAddress member : members) { + final var newE164Members = new HashSet(); + for (var member : members) { if (g.isMember(member) || !member.getNumber().isPresent()) { continue; } newE164Members.add(member.getNumber().get()); } - final Map registeredUsers = getRegisteredUsers(newE164Members); + final var registeredUsers = getRegisteredUsers(newE164Members); if (registeredUsers.size() != newE164Members.size()) { // Some of the new members are not registered on Signal newE164Members.removeAll(registeredUsers.keySet()); @@ -860,12 +836,12 @@ public class Manager implements Closeable { private Pair> sendJoinGroupMessage( GroupInviteLinkUrl inviteLinkUrl ) throws IOException, GroupLinkNotActiveException { - final DecryptedGroupJoinInfo groupJoinInfo = groupHelper.getDecryptedGroupJoinInfo(inviteLinkUrl.getGroupMasterKey(), + final var groupJoinInfo = groupHelper.getDecryptedGroupJoinInfo(inviteLinkUrl.getGroupMasterKey(), inviteLinkUrl.getPassword()); - final GroupChange groupChange = groupHelper.joinGroup(inviteLinkUrl.getGroupMasterKey(), + final var groupChange = groupHelper.joinGroup(inviteLinkUrl.getGroupMasterKey(), inviteLinkUrl.getPassword(), groupJoinInfo); - final GroupInfoV2 group = getOrMigrateGroup(inviteLinkUrl.getGroupMasterKey(), + final var group = getOrMigrateGroup(inviteLinkUrl.getGroupMasterKey(), groupJoinInfo.getRevision() + 1, groupChange.toByteArray()); @@ -874,7 +850,7 @@ public class Manager implements Closeable { return new Pair<>(group.getGroupId(), List.of()); } - final Pair> result = sendUpdateGroupMessage(group, group.getGroup(), groupChange); + final var result = sendUpdateGroupMessage(group, group.getGroup(), groupChange); return new Pair<>(group.getGroupId(), result.second()); } @@ -886,11 +862,11 @@ public class Manager implements Closeable { private GroupsV2AuthorizationString getGroupAuthForToday( final GroupSecretParams groupSecretParams ) throws IOException { - final int today = currentTimeDays(); + final var today = currentTimeDays(); // Returns credentials for the next 7 days - final HashMap credentials = groupsV2Api.getCredentials(today); + final var credentials = groupsV2Api.getCredentials(today); // TODO cache credentials until they expire - AuthCredentialResponse authCredentialResponse = credentials.get(today); + var authCredentialResponse = credentials.get(today); try { return groupsV2Api.getGroupsV2AuthorizationString(account.getUuid(), today, @@ -905,8 +881,7 @@ public class Manager implements Closeable { GroupInfoV2 group, DecryptedGroup newDecryptedGroup, GroupChange groupChange ) throws IOException { group.setGroup(newDecryptedGroup); - final SignalServiceDataMessage.Builder messageBuilder = getGroupUpdateMessageBuilder(group, - groupChange.toByteArray()); + final var messageBuilder = getGroupUpdateMessageBuilder(group, groupChange.toByteArray()); account.getGroupStore().updateGroup(group); return sendMessage(messageBuilder, group.getMembersIncludingPendingWithout(account.getSelfAddress())); } @@ -915,7 +890,7 @@ public class Manager implements Closeable { GroupIdV1 groupId, SignalServiceAddress recipient ) throws IOException, NotAGroupMemberException, GroupNotFoundException, AttachmentInvalidException { GroupInfoV1 g; - GroupInfo group = getGroupForSending(groupId); + var group = getGroupForSending(groupId); if (!(group instanceof GroupInfoV1)) { throw new RuntimeException("Received an invalid group request for a v2 group!"); } @@ -925,20 +900,20 @@ public class Manager implements Closeable { throw new NotAGroupMemberException(groupId, g.name); } - SignalServiceDataMessage.Builder messageBuilder = getGroupUpdateMessageBuilder(g); + var messageBuilder = getGroupUpdateMessageBuilder(g); // Send group message only to the recipient who requested it return sendMessage(messageBuilder, List.of(recipient)); } private SignalServiceDataMessage.Builder getGroupUpdateMessageBuilder(GroupInfoV1 g) throws AttachmentInvalidException { - SignalServiceGroup.Builder group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.UPDATE) + var group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.UPDATE) .withId(g.getGroupId().serialize()) .withName(g.name) .withMembers(new ArrayList<>(g.getMembers())); try { - final Optional attachment = createGroupAvatarAttachment(g.getGroupId()); + final var attachment = createGroupAvatarAttachment(g.getGroupId()); if (attachment.isPresent()) { group.withAvatar(attachment.get()); } @@ -952,7 +927,7 @@ public class Manager implements Closeable { } private SignalServiceDataMessage.Builder getGroupUpdateMessageBuilder(GroupInfoV2 g, byte[] signedGroupChange) { - SignalServiceGroupV2.Builder group = SignalServiceGroupV2.newBuilder(g.getMasterKey()) + var group = SignalServiceGroupV2.newBuilder(g.getMasterKey()) .withRevision(g.getGroup().getRevision()) .withSignedGroupChange(signedGroupChange); return SignalServiceDataMessage.newBuilder() @@ -963,11 +938,9 @@ public class Manager implements Closeable { Pair> sendGroupInfoRequest( GroupIdV1 groupId, SignalServiceAddress recipient ) throws IOException { - SignalServiceGroup.Builder group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.REQUEST_INFO) - .withId(groupId.serialize()); + var group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.REQUEST_INFO).withId(groupId.serialize()); - SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() - .asGroupMessage(group.build()); + var messageBuilder = SignalServiceDataMessage.newBuilder().asGroupMessage(group.build()); // Send group info request message to the recipient who sent us a message with this groupId return sendMessage(messageBuilder, List.of(recipient)); @@ -976,7 +949,7 @@ public class Manager implements Closeable { void sendReceipt( SignalServiceAddress remoteAddress, long messageId ) throws IOException, UntrustedIdentityException { - SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.DELIVERY, + var receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.DELIVERY, List.of(messageId), System.currentTimeMillis()); @@ -988,15 +961,14 @@ public class Manager implements Closeable { public Pair> sendMessage( String messageText, List attachments, List recipients ) throws IOException, AttachmentInvalidException, InvalidNumberException { - final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() - .withBody(messageText); + final var messageBuilder = SignalServiceDataMessage.newBuilder().withBody(messageText); if (attachments != null) { - List attachmentStreams = AttachmentUtils.getSignalServiceAttachments(attachments); + var attachmentStreams = AttachmentUtils.getSignalServiceAttachments(attachments); // Upload attachments here, so we only upload once even for multiple recipients - SignalServiceMessageSender messageSender = createMessageSender(); - List attachmentPointers = new ArrayList<>(attachmentStreams.size()); - for (SignalServiceAttachment attachment : attachmentStreams) { + var messageSender = createMessageSender(); + var attachmentPointers = new ArrayList(attachmentStreams.size()); + for (var attachment : attachmentStreams) { if (attachment.isStream()) { attachmentPointers.add(messageSender.uploadAttachment(attachment.asStream())); } else if (attachment.isPointer()) { @@ -1012,8 +984,7 @@ public class Manager implements Closeable { public Pair sendSelfMessage( String messageText, List attachments ) throws IOException, AttachmentInvalidException { - final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() - .withBody(messageText); + final var messageBuilder = SignalServiceDataMessage.newBuilder().withBody(messageText); if (attachments != null) { messageBuilder.withAttachments(AttachmentUtils.getSignalServiceAttachments(attachments)); } @@ -1023,23 +994,22 @@ public class Manager implements Closeable { public Pair> sendMessageReaction( String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, List recipients ) throws IOException, InvalidNumberException { - SignalServiceDataMessage.Reaction reaction = new SignalServiceDataMessage.Reaction(emoji, + var reaction = new SignalServiceDataMessage.Reaction(emoji, remove, canonicalizeAndResolveSignalServiceAddress(targetAuthor), targetSentTimestamp); - final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() - .withReaction(reaction); + final var messageBuilder = SignalServiceDataMessage.newBuilder().withReaction(reaction); return sendMessage(messageBuilder, getSignalServiceAddresses(recipients)); } public Pair> sendEndSessionMessage(List recipients) throws IOException, InvalidNumberException { - SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder().asEndSessionMessage(); + var messageBuilder = SignalServiceDataMessage.newBuilder().asEndSessionMessage(); - final Collection signalServiceAddresses = getSignalServiceAddresses(recipients); + final var signalServiceAddresses = getSignalServiceAddresses(recipients); try { return sendMessage(messageBuilder, signalServiceAddresses); } catch (Exception e) { - for (SignalServiceAddress address : signalServiceAddresses) { + for (var address : signalServiceAddresses) { handleEndSession(address); } account.save(); @@ -1048,7 +1018,7 @@ public class Manager implements Closeable { } public String getContactName(String number) throws InvalidNumberException { - ContactInfo contact = account.getContactStore().getContact(canonicalizeAndResolveSignalServiceAddress(number)); + var contact = account.getContactStore().getContact(canonicalizeAndResolveSignalServiceAddress(number)); if (contact == null) { return ""; } else { @@ -1057,8 +1027,8 @@ public class Manager implements Closeable { } public void setContactName(String number, String name) throws InvalidNumberException { - final SignalServiceAddress address = canonicalizeAndResolveSignalServiceAddress(number); - ContactInfo contact = account.getContactStore().getContact(address); + final var address = canonicalizeAndResolveSignalServiceAddress(number); + var contact = account.getContactStore().getContact(address); if (contact == null) { contact = new ContactInfo(address); } @@ -1072,7 +1042,7 @@ public class Manager implements Closeable { } private void setContactBlocked(SignalServiceAddress address, boolean blocked) { - ContactInfo contact = account.getContactStore().getContact(address); + var contact = account.getContactStore().getContact(address); if (contact == null) { contact = new ContactInfo(address); } @@ -1082,7 +1052,7 @@ public class Manager implements Closeable { } public void setGroupBlocked(final GroupId groupId, final boolean blocked) throws GroupNotFoundException { - GroupInfo group = getGroup(groupId); + var group = getGroup(groupId); if (group == null) { throw new GroupNotFoundException(groupId); } @@ -1096,7 +1066,7 @@ public class Manager implements Closeable { * Change the expiration timer for a contact */ public void setExpirationTimer(SignalServiceAddress address, int messageExpirationTimer) throws IOException { - ContactInfo contact = account.getContactStore().getContact(address); + var contact = account.getContactStore().getContact(address); contact.messageExpirationTime = messageExpirationTimer; account.getContactStore().updateContact(contact); sendExpirationTimerUpdate(address); @@ -1104,8 +1074,7 @@ public class Manager implements Closeable { } private void sendExpirationTimerUpdate(SignalServiceAddress address) throws IOException { - final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() - .asExpirationUpdate(); + final var messageBuilder = SignalServiceDataMessage.newBuilder().asExpirationUpdate(); sendMessage(messageBuilder, List.of(address)); } @@ -1115,7 +1084,7 @@ public class Manager implements Closeable { public void setExpirationTimer( String number, int messageExpirationTimer ) throws IOException, InvalidNumberException { - SignalServiceAddress address = canonicalizeAndResolveSignalServiceAddress(number); + var address = canonicalizeAndResolveSignalServiceAddress(number); setExpirationTimer(address, messageExpirationTimer); } @@ -1123,9 +1092,9 @@ public class Manager implements Closeable { * Change the expiration timer for a group */ public void setExpirationTimer(GroupId groupId, int messageExpirationTimer) { - GroupInfo g = getGroup(groupId); + var g = getGroup(groupId); if (g instanceof GroupInfoV1) { - GroupInfoV1 groupInfoV1 = (GroupInfoV1) g; + var groupInfoV1 = (GroupInfoV1) g; groupInfoV1.messageExpirationTime = messageExpirationTimer; account.getGroupStore().updateGroup(groupInfoV1); } else { @@ -1140,14 +1109,14 @@ public class Manager implements Closeable { * @return if successful, returns the URL to install the sticker pack in the signal app */ public String uploadStickerPack(File path) throws IOException, StickerPackInvalidException { - SignalServiceStickerManifestUpload manifest = StickerUtils.getSignalServiceStickerManifestUpload(path); + var manifest = StickerUtils.getSignalServiceStickerManifestUpload(path); - SignalServiceMessageSender messageSender = createMessageSender(); + var messageSender = createMessageSender(); - byte[] packKey = KeyUtils.createStickerUploadKey(); - String packId = messageSender.uploadStickerManifest(manifest, packKey); + var packKey = KeyUtils.createStickerUploadKey(); + var packId = messageSender.uploadStickerManifest(manifest, packKey); - Sticker sticker = new Sticker(Hex.fromStringCondensed(packId), packKey); + var sticker = new Sticker(Hex.fromStringCondensed(packId), packKey); account.getStickerStore().updateSticker(sticker); account.save(); @@ -1164,10 +1133,10 @@ public class Manager implements Closeable { } void requestSyncGroups() throws IOException { - SignalServiceProtos.SyncMessage.Request r = SignalServiceProtos.SyncMessage.Request.newBuilder() + var r = SignalServiceProtos.SyncMessage.Request.newBuilder() .setType(SignalServiceProtos.SyncMessage.Request.Type.GROUPS) .build(); - SignalServiceSyncMessage message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); + var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); try { sendSyncMessage(message); } catch (UntrustedIdentityException e) { @@ -1176,10 +1145,10 @@ public class Manager implements Closeable { } void requestSyncContacts() throws IOException { - SignalServiceProtos.SyncMessage.Request r = SignalServiceProtos.SyncMessage.Request.newBuilder() + var r = SignalServiceProtos.SyncMessage.Request.newBuilder() .setType(SignalServiceProtos.SyncMessage.Request.Type.CONTACTS) .build(); - SignalServiceSyncMessage message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); + var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); try { sendSyncMessage(message); } catch (UntrustedIdentityException e) { @@ -1188,10 +1157,10 @@ public class Manager implements Closeable { } void requestSyncBlocked() throws IOException { - SignalServiceProtos.SyncMessage.Request r = SignalServiceProtos.SyncMessage.Request.newBuilder() + var r = SignalServiceProtos.SyncMessage.Request.newBuilder() .setType(SignalServiceProtos.SyncMessage.Request.Type.BLOCKED) .build(); - SignalServiceSyncMessage message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); + var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); try { sendSyncMessage(message); } catch (UntrustedIdentityException e) { @@ -1200,10 +1169,10 @@ public class Manager implements Closeable { } void requestSyncConfiguration() throws IOException { - SignalServiceProtos.SyncMessage.Request r = SignalServiceProtos.SyncMessage.Request.newBuilder() + var r = SignalServiceProtos.SyncMessage.Request.newBuilder() .setType(SignalServiceProtos.SyncMessage.Request.Type.CONFIGURATION) .build(); - SignalServiceSyncMessage message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); + var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); try { sendSyncMessage(message); } catch (UntrustedIdentityException e) { @@ -1212,10 +1181,10 @@ public class Manager implements Closeable { } void requestSyncKeys() throws IOException { - SignalServiceProtos.SyncMessage.Request r = SignalServiceProtos.SyncMessage.Request.newBuilder() + var r = SignalServiceProtos.SyncMessage.Request.newBuilder() .setType(SignalServiceProtos.SyncMessage.Request.Type.KEYS) .build(); - SignalServiceSyncMessage message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); + var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); try { sendSyncMessage(message); } catch (UntrustedIdentityException e) { @@ -1238,7 +1207,7 @@ public class Manager implements Closeable { } private void sendSyncMessage(SignalServiceSyncMessage message) throws IOException, UntrustedIdentityException { - SignalServiceMessageSender messageSender = createMessageSender(); + var messageSender = createMessageSender(); try { messageSender.sendMessage(message, unidentifiedAccessHelper.getAccessForSync()); } catch (UntrustedIdentityException e) { @@ -1251,11 +1220,11 @@ public class Manager implements Closeable { } private Collection getSignalServiceAddresses(Collection numbers) throws InvalidNumberException { - final Set signalServiceAddresses = new HashSet<>(numbers.size()); - final Set addressesMissingUuid = new HashSet<>(); + final var signalServiceAddresses = new HashSet(numbers.size()); + final var addressesMissingUuid = new HashSet(); - for (String number : numbers) { - final SignalServiceAddress resolvedAddress = canonicalizeAndResolveSignalServiceAddress(number); + for (var number : numbers) { + final var resolvedAddress = canonicalizeAndResolveSignalServiceAddress(number); if (resolvedAddress.getUuid().isPresent()) { signalServiceAddresses.add(resolvedAddress); } else { @@ -1263,7 +1232,7 @@ public class Manager implements Closeable { } } - final Set numbersMissingUuid = addressesMissingUuid.stream() + final var numbersMissingUuid = addressesMissingUuid.stream() .map(a -> a.getNumber().get()) .collect(Collectors.toSet()); Map registeredUsers; @@ -1274,11 +1243,10 @@ public class Manager implements Closeable { registeredUsers = Map.of(); } - for (SignalServiceAddress address : addressesMissingUuid) { - final String number = address.getNumber().get(); + for (var address : addressesMissingUuid) { + final var number = address.getNumber().get(); if (registeredUsers.containsKey(number)) { - final SignalServiceAddress newAddress = resolveSignalServiceAddress(new SignalServiceAddress( - registeredUsers.get(number), + final var newAddress = resolveSignalServiceAddress(new SignalServiceAddress(registeredUsers.get(number), number)); signalServiceAddresses.add(newAddress); } else { @@ -1303,7 +1271,7 @@ public class Manager implements Closeable { SignalServiceDataMessage.Builder messageBuilder, Collection recipients ) throws IOException { recipients = recipients.stream().map(this::resolveSignalServiceAddress).collect(Collectors.toSet()); - final long timestamp = System.currentTimeMillis(); + final var timestamp = System.currentTimeMillis(); messageBuilder.withTimestamp(timestamp); getOrCreateMessagePipe(); getOrCreateUnidentifiedMessagePipe(); @@ -1312,13 +1280,13 @@ public class Manager implements Closeable { message = messageBuilder.build(); if (message.getGroupContext().isPresent()) { try { - SignalServiceMessageSender messageSender = createMessageSender(); - final boolean isRecipientUpdate = false; - List result = messageSender.sendMessage(new ArrayList<>(recipients), + var messageSender = createMessageSender(); + final var isRecipientUpdate = false; + var result = messageSender.sendMessage(new ArrayList<>(recipients), unidentifiedAccessHelper.getAccessFor(recipients), isRecipientUpdate, message); - for (SendMessageResult r : result) { + for (var r : result) { if (r.getIdentityFailure() != null) { account.getSignalProtocolStore() .saveIdentity(r.getAddress(), @@ -1337,10 +1305,10 @@ public class Manager implements Closeable { } else { // Send to all individually, so sync messages are sent correctly messageBuilder.withProfileKey(account.getProfileKey().serialize()); - List results = new ArrayList<>(recipients.size()); - for (SignalServiceAddress address : recipients) { - final ContactInfo contact = account.getContactStore().getContact(address); - final int expirationTime = contact != null ? contact.messageExpirationTime : 0; + var results = new ArrayList(recipients.size()); + for (var address : recipients) { + final var contact = account.getContactStore().getContact(address); + final var expirationTime = contact != null ? contact.messageExpirationTime : 0; messageBuilder.withExpiration(expirationTime); message = messageBuilder.build(); results.add(sendMessage(address, message)); @@ -1349,7 +1317,7 @@ public class Manager implements Closeable { } } finally { if (message != null && message.isEndSession()) { - for (SignalServiceAddress recipient : recipients) { + for (var recipient : recipients) { handleEndSession(recipient); } } @@ -1360,19 +1328,19 @@ public class Manager implements Closeable { private Pair sendSelfMessage( SignalServiceDataMessage.Builder messageBuilder ) throws IOException { - final long timestamp = System.currentTimeMillis(); + final var timestamp = System.currentTimeMillis(); messageBuilder.withTimestamp(timestamp); getOrCreateMessagePipe(); getOrCreateUnidentifiedMessagePipe(); try { - final SignalServiceAddress address = getSelfAddress(); + final var address = getSelfAddress(); - final ContactInfo contact = account.getContactStore().getContact(address); - final int expirationTime = contact != null ? contact.messageExpirationTime : 0; + final var contact = account.getContactStore().getContact(address); + final var expirationTime = contact != null ? contact.messageExpirationTime : 0; messageBuilder.withExpiration(expirationTime); - SignalServiceDataMessage message = messageBuilder.build(); - final SendMessageResult result = sendSelfMessage(message); + var message = messageBuilder.build(); + final var result = sendSelfMessage(message); return new Pair<>(timestamp, result); } finally { account.save(); @@ -1380,21 +1348,21 @@ public class Manager implements Closeable { } private SendMessageResult sendSelfMessage(SignalServiceDataMessage message) throws IOException { - SignalServiceMessageSender messageSender = createMessageSender(); + var messageSender = createMessageSender(); - SignalServiceAddress recipient = account.getSelfAddress(); + var recipient = account.getSelfAddress(); - final Optional unidentifiedAccess = unidentifiedAccessHelper.getAccessFor(recipient); - SentTranscriptMessage transcript = new SentTranscriptMessage(Optional.of(recipient), + final var unidentifiedAccess = unidentifiedAccessHelper.getAccessFor(recipient); + var transcript = new SentTranscriptMessage(Optional.of(recipient), message.getTimestamp(), message, message.getExpiresInSeconds(), Map.of(recipient, unidentifiedAccess.isPresent()), false); - SignalServiceSyncMessage syncMessage = SignalServiceSyncMessage.forSentTranscript(transcript); + var syncMessage = SignalServiceSyncMessage.forSentTranscript(transcript); try { - long startTime = System.currentTimeMillis(); + var startTime = System.currentTimeMillis(); messageSender.sendMessage(syncMessage, unidentifiedAccess); return SendMessageResult.success(recipient, unidentifiedAccess.isPresent(), @@ -1412,7 +1380,7 @@ public class Manager implements Closeable { private SendMessageResult sendMessage( SignalServiceAddress address, SignalServiceDataMessage message ) throws IOException { - SignalServiceMessageSender messageSender = createMessageSender(); + var messageSender = createMessageSender(); try { return messageSender.sendMessage(address, unidentifiedAccessHelper.getAccessFor(address), message); @@ -1426,16 +1394,15 @@ public class Manager implements Closeable { } private SignalServiceContent decryptMessage(SignalServiceEnvelope envelope) throws InvalidMetadataMessageException, ProtocolInvalidMessageException, ProtocolDuplicateMessageException, ProtocolLegacyMessageException, ProtocolInvalidKeyIdException, InvalidMetadataVersionException, ProtocolInvalidVersionException, ProtocolNoSessionException, ProtocolInvalidKeyException, SelfSendException, UnsupportedDataMessageException, org.whispersystems.libsignal.UntrustedIdentityException { - SignalServiceCipher cipher = new SignalServiceCipher(account.getSelfAddress(), + var cipher = new SignalServiceCipher(account.getSelfAddress(), account.getSignalProtocolStore(), certificateValidator); try { return cipher.decrypt(envelope); } catch (ProtocolUntrustedIdentityException e) { if (e.getCause() instanceof org.whispersystems.libsignal.UntrustedIdentityException) { - org.whispersystems.libsignal.UntrustedIdentityException identityException = (org.whispersystems.libsignal.UntrustedIdentityException) e - .getCause(); - final IdentityKey untrustedIdentity = identityException.getUntrustedIdentity(); + var identityException = (org.whispersystems.libsignal.UntrustedIdentityException) e.getCause(); + final var untrustedIdentity = identityException.getUntrustedIdentity(); if (untrustedIdentity != null) { account.getSignalProtocolStore() .saveIdentity(resolveSignalServiceAddress(identityException.getName()), @@ -1459,14 +1426,14 @@ public class Manager implements Closeable { SignalServiceAddress destination, boolean ignoreAttachments ) { - List actions = new ArrayList<>(); + var actions = new ArrayList(); if (message.getGroupContext().isPresent()) { if (message.getGroupContext().get().getGroupV1().isPresent()) { - SignalServiceGroup groupInfo = message.getGroupContext().get().getGroupV1().get(); - GroupIdV1 groupId = GroupId.v1(groupInfo.getGroupId()); - GroupInfo group = getGroup(groupId); + var groupInfo = message.getGroupContext().get().getGroupV1().get(); + var groupId = GroupId.v1(groupInfo.getGroupId()); + var group = getGroup(groupId); if (group == null || group instanceof GroupInfoV1) { - GroupInfoV1 groupV1 = (GroupInfoV1) group; + var groupV1 = (GroupInfoV1) group; switch (groupInfo.getType()) { case UPDATE: { if (groupV1 == null) { @@ -1474,7 +1441,7 @@ public class Manager implements Closeable { } if (groupInfo.getAvatar().isPresent()) { - SignalServiceAttachment avatar = groupInfo.getAvatar().get(); + var avatar = groupInfo.getAvatar().get(); downloadGroupAvatar(avatar, groupV1.getGroupId()); } @@ -1516,8 +1483,8 @@ public class Manager implements Closeable { } } if (message.getGroupContext().get().getGroupV2().isPresent()) { - final SignalServiceGroupV2 groupContext = message.getGroupContext().get().getGroupV2().get(); - final GroupMasterKey groupMasterKey = groupContext.getMasterKey(); + final var groupContext = message.getGroupContext().get().getGroupV2().get(); + final var groupMasterKey = groupContext.getMasterKey(); getOrMigrateGroup(groupMasterKey, groupContext.getRevision(), @@ -1525,15 +1492,15 @@ public class Manager implements Closeable { } } - final SignalServiceAddress conversationPartnerAddress = isSync ? destination : source; + final var conversationPartnerAddress = isSync ? destination : source; if (conversationPartnerAddress != null && message.isEndSession()) { handleEndSession(conversationPartnerAddress); } if (message.isExpirationUpdate() || message.getBody().isPresent()) { if (message.getGroupContext().isPresent()) { if (message.getGroupContext().get().getGroupV1().isPresent()) { - SignalServiceGroup groupInfo = message.getGroupContext().get().getGroupV1().get(); - GroupInfoV1 group = account.getGroupStore().getOrCreateGroupV1(GroupId.v1(groupInfo.getGroupId())); + var groupInfo = message.getGroupContext().get().getGroupV1().get(); + var group = account.getGroupStore().getOrCreateGroupV1(GroupId.v1(groupInfo.getGroupId())); if (group != null) { if (group.messageExpirationTime != message.getExpiresInSeconds()) { group.messageExpirationTime = message.getExpiresInSeconds(); @@ -1544,7 +1511,7 @@ public class Manager implements Closeable { // disappearing message timer already stored in the DecryptedGroup } } else if (conversationPartnerAddress != null) { - ContactInfo contact = account.getContactStore().getContact(conversationPartnerAddress); + var contact = account.getContactStore().getContact(conversationPartnerAddress); if (contact == null) { contact = new ContactInfo(conversationPartnerAddress); } @@ -1556,12 +1523,12 @@ public class Manager implements Closeable { } if (!ignoreAttachments) { if (message.getAttachments().isPresent()) { - for (SignalServiceAttachment attachment : message.getAttachments().get()) { + for (var attachment : message.getAttachments().get()) { downloadAttachment(attachment); } } if (message.getSharedContacts().isPresent()) { - for (SharedContact contact : message.getSharedContacts().get()) { + for (var contact : message.getSharedContacts().get()) { if (contact.getAvatar().isPresent()) { downloadAttachment(contact.getAvatar().get().getAttachment()); } @@ -1581,26 +1548,26 @@ public class Manager implements Closeable { this.account.getProfileStore().storeProfileKey(source, profileKey); } if (message.getPreviews().isPresent()) { - final List previews = message.getPreviews().get(); - for (SignalServiceDataMessage.Preview preview : previews) { + final var previews = message.getPreviews().get(); + for (var preview : previews) { if (preview.getImage().isPresent()) { downloadAttachment(preview.getImage().get()); } } } if (message.getQuote().isPresent()) { - final SignalServiceDataMessage.Quote quote = message.getQuote().get(); + final var quote = message.getQuote().get(); - for (SignalServiceDataMessage.Quote.QuotedAttachment quotedAttachment : quote.getAttachments()) { - final SignalServiceAttachment thumbnail = quotedAttachment.getThumbnail(); + for (var quotedAttachment : quote.getAttachments()) { + final var thumbnail = quotedAttachment.getThumbnail(); if (thumbnail != null) { downloadAttachment(thumbnail); } } } if (message.getSticker().isPresent()) { - final SignalServiceDataMessage.Sticker messageSticker = message.getSticker().get(); - Sticker sticker = account.getStickerStore().getSticker(messageSticker.getPackId()); + final var messageSticker = message.getSticker().get(); + var sticker = account.getStickerStore().getSticker(messageSticker.getPackId()); if (sticker == null) { sticker = new Sticker(messageSticker.getPackId(), messageSticker.getPackKey()); account.getStickerStore().updateSticker(sticker); @@ -1612,10 +1579,10 @@ public class Manager implements Closeable { private GroupInfoV2 getOrMigrateGroup( final GroupMasterKey groupMasterKey, final int revision, final byte[] signedGroupChange ) { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); - GroupIdV2 groupId = GroupUtils.getGroupIdV2(groupSecretParams); - GroupInfo groupInfo = getGroup(groupId); + var groupId = GroupUtils.getGroupIdV2(groupSecretParams); + var groupInfo = getGroup(groupId); final GroupInfoV2 groupInfoV2; if (groupInfo instanceof GroupInfoV1) { // Received a v2 group message for a v1 group, we need to locally migrate the group @@ -1642,7 +1609,7 @@ public class Manager implements Closeable { } if (group != null) { storeProfileKeysFromMembers(group); - final String avatar = group.getAvatar(); + final var avatar = group.getAvatar(); if (avatar != null && !avatar.isEmpty()) { downloadGroupAvatar(groupId, groupSecretParams, avatar); } @@ -1655,9 +1622,9 @@ public class Manager implements Closeable { } private void storeProfileKeysFromMembers(final DecryptedGroup group) { - for (DecryptedMember member : group.getMembersList()) { - final SignalServiceAddress address = resolveSignalServiceAddress(new SignalServiceAddress(UuidUtil.parseOrThrow( - member.getUuid().toByteArray()), null)); + for (var member : group.getMembersList()) { + final var address = resolveSignalServiceAddress(new SignalServiceAddress(UuidUtil.parseOrThrow(member.getUuid() + .toByteArray()), null)); try { account.getProfileStore() .storeProfileKey(address, new ProfileKey(member.getProfileKey().toByteArray())); @@ -1667,7 +1634,7 @@ public class Manager implements Closeable { } private void retryFailedReceivedMessages(ReceiveMessageHandler handler, boolean ignoreAttachments) { - for (CachedMessage cachedMessage : account.getMessageCache().getCachedMessages()) { + for (var cachedMessage : account.getMessageCache().getCachedMessages()) { retryFailedReceivedMessage(handler, ignoreAttachments, cachedMessage); } } @@ -1675,7 +1642,7 @@ public class Manager implements Closeable { private void retryFailedReceivedMessage( final ReceiveMessageHandler handler, final boolean ignoreAttachments, final CachedMessage cachedMessage ) { - SignalServiceEnvelope envelope = cachedMessage.loadEnvelope(); + var envelope = cachedMessage.loadEnvelope(); if (envelope == null) { return; } @@ -1690,8 +1657,8 @@ public class Manager implements Closeable { cachedMessage.delete(); return; } - List actions = handleMessage(envelope, content, ignoreAttachments); - for (HandleAction action : actions) { + var actions = handleMessage(envelope, content, ignoreAttachments); + for (var action : actions) { try { action.execute(this); } catch (Throwable e) { @@ -1715,9 +1682,9 @@ public class Manager implements Closeable { Set queuedActions = null; - final SignalServiceMessagePipe messagePipe = getOrCreateMessagePipe(); + final var messagePipe = getOrCreateMessagePipe(); - boolean hasCaughtUpWithOldMessages = false; + var hasCaughtUpWithOldMessages = false; while (true) { SignalServiceEnvelope envelope; @@ -1725,7 +1692,7 @@ public class Manager implements Closeable { Exception exception = null; final CachedMessage[] cachedMessage = {null}; try { - Optional result = messagePipe.readOrEmpty(timeout, unit, envelope1 -> { + var result = messagePipe.readOrEmpty(timeout, unit, envelope1 -> { // store message on disk, before acknowledging receipt to the server cachedMessage[0] = account.getMessageCache().cacheMessage(envelope1); }); @@ -1736,7 +1703,7 @@ public class Manager implements Closeable { hasCaughtUpWithOldMessages = true; if (queuedActions != null) { - for (HandleAction action : queuedActions) { + for (var action : queuedActions) { try { action.execute(this); } catch (Throwable e) { @@ -1758,7 +1725,7 @@ public class Manager implements Closeable { if (envelope.hasSource()) { // Store uuid if we don't have it already - SignalServiceAddress source = envelope.getSourceAddress(); + var source = envelope.getSourceAddress(); resolveSignalServiceAddress(source); } if (!envelope.isReceipt()) { @@ -1767,9 +1734,9 @@ public class Manager implements Closeable { } catch (Exception e) { exception = e; } - List actions = handleMessage(envelope, content, ignoreAttachments); + var actions = handleMessage(envelope, content, ignoreAttachments); if (hasCaughtUpWithOldMessages) { - for (HandleAction action : actions) { + for (var action : actions) { try { action.execute(this); } catch (Throwable e) { @@ -1810,16 +1777,16 @@ public class Manager implements Closeable { } else { return false; } - ContactInfo sourceContact = account.getContactStore().getContact(source); + var sourceContact = account.getContactStore().getContact(source); if (sourceContact != null && sourceContact.blocked) { return true; } if (content != null && content.getDataMessage().isPresent()) { - SignalServiceDataMessage message = content.getDataMessage().get(); + var message = content.getDataMessage().get(); if (message.getGroupContext().isPresent()) { - GroupId groupId = GroupUtils.getGroupId(message.getGroupContext().get()); - GroupInfo group = getGroup(groupId); + var groupId = GroupUtils.getGroupId(message.getGroupContext().get()); + var group = getGroup(groupId); if (group != null && group.isBlocked()) { return true; } @@ -1841,16 +1808,16 @@ public class Manager implements Closeable { } if (content != null && content.getDataMessage().isPresent()) { - SignalServiceDataMessage message = content.getDataMessage().get(); + var message = content.getDataMessage().get(); if (message.getGroupContext().isPresent()) { if (message.getGroupContext().get().getGroupV1().isPresent()) { - SignalServiceGroup groupInfo = message.getGroupContext().get().getGroupV1().get(); + var groupInfo = message.getGroupContext().get().getGroupV1().get(); if (groupInfo.getType() == SignalServiceGroup.Type.QUIT) { return false; } } - GroupId groupId = GroupUtils.getGroupId(message.getGroupContext().get()); - GroupInfo group = getGroup(groupId); + var groupId = GroupUtils.getGroupId(message.getGroupContext().get()); + var group = getGroup(groupId); if (group != null && !group.isMember(source)) { return true; } @@ -1862,7 +1829,7 @@ public class Manager implements Closeable { private List handleMessage( SignalServiceEnvelope envelope, SignalServiceContent content, boolean ignoreAttachments ) { - List actions = new ArrayList<>(); + var actions = new ArrayList(); if (content != null) { final SignalServiceAddress sender; if (!envelope.isUnidentifiedSender() && envelope.hasSource()) { @@ -1874,7 +1841,7 @@ public class Manager implements Closeable { resolveSignalServiceAddress(sender); if (content.getDataMessage().isPresent()) { - SignalServiceDataMessage message = content.getDataMessage().get(); + var message = content.getDataMessage().get(); if (content.isNeedsReceipt()) { actions.add(new SendReceiptAction(sender, message.getTimestamp())); @@ -1888,10 +1855,10 @@ public class Manager implements Closeable { } if (content.getSyncMessage().isPresent()) { account.setMultiDevice(true); - SignalServiceSyncMessage syncMessage = content.getSyncMessage().get(); + var syncMessage = content.getSyncMessage().get(); if (syncMessage.getSent().isPresent()) { - SentTranscriptMessage message = syncMessage.getSent().get(); - final SignalServiceAddress destination = message.getDestination().orNull(); + var message = syncMessage.getSent().get(); + final var destination = message.getDestination().orNull(); actions.addAll(handleSignalServiceDataMessage(message.getMessage(), true, sender, @@ -1899,7 +1866,7 @@ public class Manager implements Closeable { ignoreAttachments)); } if (syncMessage.getRequest().isPresent()) { - RequestMessage rm = syncMessage.getRequest().get(); + var rm = syncMessage.getRequest().get(); if (rm.isContactsRequest()) { actions.add(SendSyncContactsAction.create()); } @@ -1915,14 +1882,12 @@ public class Manager implements Closeable { File tmpFile = null; try { tmpFile = IOUtils.createTempFile(); - final SignalServiceAttachment groupsMessage = syncMessage.getGroups().get(); - try (InputStream attachmentAsStream = retrieveAttachmentAsStream(groupsMessage.asPointer(), - tmpFile)) { - DeviceGroupsInputStream s = new DeviceGroupsInputStream(attachmentAsStream); + final var groupsMessage = syncMessage.getGroups().get(); + try (var attachmentAsStream = retrieveAttachmentAsStream(groupsMessage.asPointer(), tmpFile)) { + var s = new DeviceGroupsInputStream(attachmentAsStream); DeviceGroup g; while ((g = s.read()) != null) { - GroupInfoV1 syncGroup = account.getGroupStore() - .getOrCreateGroupV1(GroupId.v1(g.getId())); + var syncGroup = account.getGroupStore().getOrCreateGroupV1(GroupId.v1(g.getId())); if (syncGroup != null) { if (g.getName().isPresent()) { syncGroup.name = g.getName().get(); @@ -1968,11 +1933,11 @@ public class Manager implements Closeable { } } if (syncMessage.getBlockedList().isPresent()) { - final BlockedListMessage blockedListMessage = syncMessage.getBlockedList().get(); - for (SignalServiceAddress address : blockedListMessage.getAddresses()) { + final var blockedListMessage = syncMessage.getBlockedList().get(); + for (var address : blockedListMessage.getAddresses()) { setContactBlocked(resolveSignalServiceAddress(address), true); } - for (GroupId groupId : blockedListMessage.getGroupIds() + for (var groupId : blockedListMessage.getGroupIds() .stream() .map(GroupId::unknownVersion) .collect(Collectors.toSet())) { @@ -1988,10 +1953,10 @@ public class Manager implements Closeable { File tmpFile = null; try { tmpFile = IOUtils.createTempFile(); - final ContactsMessage contactsMessage = syncMessage.getContacts().get(); - try (InputStream attachmentAsStream = retrieveAttachmentAsStream(contactsMessage.getContactsStream() + final var contactsMessage = syncMessage.getContacts().get(); + try (var attachmentAsStream = retrieveAttachmentAsStream(contactsMessage.getContactsStream() .asPointer(), tmpFile)) { - DeviceContactsInputStream s = new DeviceContactsInputStream(attachmentAsStream); + var s = new DeviceContactsInputStream(attachmentAsStream); if (contactsMessage.isComplete()) { account.getContactStore().clear(); } @@ -2000,8 +1965,8 @@ public class Manager implements Closeable { if (c.getAddress().matches(account.getSelfAddress()) && c.getProfileKey().isPresent()) { account.setProfileKey(c.getProfileKey().get()); } - final SignalServiceAddress address = resolveSignalServiceAddress(c.getAddress()); - ContactInfo contact = account.getContactStore().getContact(address); + final var address = resolveSignalServiceAddress(c.getAddress()); + var contact = account.getContactStore().getContact(address); if (contact == null) { contact = new ContactInfo(address); } @@ -2015,7 +1980,7 @@ public class Manager implements Closeable { account.getProfileStore().storeProfileKey(address, c.getProfileKey().get()); } if (c.getVerified().isPresent()) { - final VerifiedMessage verifiedMessage = c.getVerified().get(); + final var verifiedMessage = c.getVerified().get(); account.getSignalProtocolStore() .setIdentityTrustLevel(verifiedMessage.getDestination(), verifiedMessage.getIdentityKey(), @@ -2051,20 +2016,19 @@ public class Manager implements Closeable { } } if (syncMessage.getVerified().isPresent()) { - final VerifiedMessage verifiedMessage = syncMessage.getVerified().get(); + final var verifiedMessage = syncMessage.getVerified().get(); account.getSignalProtocolStore() .setIdentityTrustLevel(resolveSignalServiceAddress(verifiedMessage.getDestination()), verifiedMessage.getIdentityKey(), TrustLevel.fromVerifiedState(verifiedMessage.getVerified())); } if (syncMessage.getStickerPackOperations().isPresent()) { - final List stickerPackOperationMessages = syncMessage.getStickerPackOperations() - .get(); - for (StickerPackOperationMessage m : stickerPackOperationMessages) { + final var stickerPackOperationMessages = syncMessage.getStickerPackOperations().get(); + for (var m : stickerPackOperationMessages) { if (!m.getPackId().isPresent()) { continue; } - Sticker sticker = account.getStickerStore().getSticker(m.getPackId().get()); + var sticker = account.getStickerStore().getSticker(m.getPackId().get()); if (sticker == null) { if (!m.getPackKey().isPresent()) { continue; @@ -2085,9 +2049,9 @@ public class Manager implements Closeable { } } if (syncMessage.getKeys().isPresent()) { - final KeysMessage keysMessage = syncMessage.getKeys().get(); + final var keysMessage = syncMessage.getKeys().get(); if (keysMessage.getStorageService().isPresent()) { - final StorageKey storageKey = keysMessage.getStorageService().get(); + final var storageKey = keysMessage.getStorageService().get(); account.setStorageKey(storageKey); } } @@ -2144,9 +2108,9 @@ public class Manager implements Closeable { logger.warn("Invalid state, can't store an attachment stream."); } - SignalServiceAttachmentPointer pointer = attachment.asPointer(); + var pointer = attachment.asPointer(); if (pointer.getPreview().isPresent()) { - final byte[] preview = pointer.getPreview().get(); + final var preview = pointer.getPreview().get(); try { attachmentStore.storeAttachmentPreview(pointer.getRemoteId(), outputStream -> outputStream.write(preview, 0, preview.length)); @@ -2166,15 +2130,15 @@ public class Manager implements Closeable { private void retrieveGroupV2Avatar( GroupSecretParams groupSecretParams, String cdnKey, OutputStream outputStream ) throws IOException { - GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); + var groupOperations = groupsV2Operations.forGroup(groupSecretParams); - File tmpFile = IOUtils.createTempFile(); + var tmpFile = IOUtils.createTempFile(); try (InputStream input = messageReceiver.retrieveGroupsV2ProfileAvatar(cdnKey, tmpFile, ServiceConfig.AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE)) { - byte[] encryptedData = IOUtils.readFully(input); + var encryptedData = IOUtils.readFully(input); - byte[] decryptedData = groupOperations.decryptAvatar(encryptedData); + var decryptedData = groupOperations.decryptAvatar(encryptedData); outputStream.write(decryptedData); } finally { try { @@ -2190,8 +2154,8 @@ public class Manager implements Closeable { private void retrieveProfileAvatar( String avatarPath, ProfileKey profileKey, OutputStream outputStream ) throws IOException { - File tmpFile = IOUtils.createTempFile(); - try (InputStream input = messageReceiver.retrieveProfileAvatar(avatarPath, + var tmpFile = IOUtils.createTempFile(); + try (var input = messageReceiver.retrieveProfileAvatar(avatarPath, tmpFile, profileKey, ServiceConfig.AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE)) { @@ -2212,10 +2176,10 @@ public class Manager implements Closeable { final SignalServiceAttachment attachment, final OutputStream outputStream ) throws IOException { if (attachment.isPointer()) { - SignalServiceAttachmentPointer pointer = attachment.asPointer(); + var pointer = attachment.asPointer(); retrieveAttachmentPointer(pointer, outputStream); } else { - SignalServiceAttachmentStream stream = attachment.asStream(); + var stream = attachment.asStream(); IOUtils.copyStream(stream.getInputStream(), outputStream); } } @@ -2223,8 +2187,8 @@ public class Manager implements Closeable { private void retrieveAttachmentPointer( SignalServiceAttachmentPointer pointer, OutputStream outputStream ) throws IOException { - File tmpFile = IOUtils.createTempFile(); - try (InputStream input = retrieveAttachmentAsStream(pointer, tmpFile)) { + var tmpFile = IOUtils.createTempFile(); + try (var input = retrieveAttachmentAsStream(pointer, tmpFile)) { IOUtils.copyStream(input, outputStream); } catch (MissingConfigurationException | InvalidMessageException e) { throw new IOException(e); @@ -2246,14 +2210,14 @@ public class Manager implements Closeable { } void sendGroups() throws IOException, UntrustedIdentityException { - File groupsFile = IOUtils.createTempFile(); + var groupsFile = IOUtils.createTempFile(); try { try (OutputStream fos = new FileOutputStream(groupsFile)) { - DeviceGroupsOutputStream out = new DeviceGroupsOutputStream(fos); - for (GroupInfo record : getGroups()) { + var out = new DeviceGroupsOutputStream(fos); + for (var record : getGroups()) { if (record instanceof GroupInfoV1) { - GroupInfoV1 groupInfo = (GroupInfoV1) record; + var groupInfo = (GroupInfoV1) record; out.write(new DeviceGroup(groupInfo.getGroupId().serialize(), Optional.fromNullable(groupInfo.name), new ArrayList<>(groupInfo.getMembers()), @@ -2269,8 +2233,8 @@ public class Manager implements Closeable { } if (groupsFile.exists() && groupsFile.length() > 0) { - try (FileInputStream groupsFileStream = new FileInputStream(groupsFile)) { - SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder() + try (var groupsFileStream = new FileInputStream(groupsFile)) { + var attachmentStream = SignalServiceAttachment.newStreamBuilder() .withStream(groupsFileStream) .withContentType("application/octet-stream") .withLength(groupsFile.length()) @@ -2289,14 +2253,14 @@ public class Manager implements Closeable { } public void sendContacts() throws IOException, UntrustedIdentityException { - File contactsFile = IOUtils.createTempFile(); + var contactsFile = IOUtils.createTempFile(); try { try (OutputStream fos = new FileOutputStream(contactsFile)) { - DeviceContactsOutputStream out = new DeviceContactsOutputStream(fos); - for (ContactInfo record : account.getContactStore().getContacts()) { + var out = new DeviceContactsOutputStream(fos); + for (var record : account.getContactStore().getContacts()) { VerifiedMessage verifiedMessage = null; - IdentityInfo currentIdentity = account.getSignalProtocolStore().getIdentity(record.getAddress()); + var currentIdentity = account.getSignalProtocolStore().getIdentity(record.getAddress()); if (currentIdentity != null) { verifiedMessage = new VerifiedMessage(record.getAddress(), currentIdentity.getIdentityKey(), @@ -2304,7 +2268,7 @@ public class Manager implements Closeable { currentIdentity.getDateAdded().getTime()); } - ProfileKey profileKey = account.getProfileStore().getProfileKey(record.getAddress()); + var profileKey = account.getProfileStore().getProfileKey(record.getAddress()); out.write(new DeviceContact(record.getAddress(), Optional.fromNullable(record.name), createContactAvatarAttachment(record.getAddress()), @@ -2333,8 +2297,8 @@ public class Manager implements Closeable { } if (contactsFile.exists() && contactsFile.length() > 0) { - try (FileInputStream contactsFileStream = new FileInputStream(contactsFile)) { - SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder() + try (var contactsFileStream = new FileInputStream(contactsFile)) { + var attachmentStream = SignalServiceAttachment.newStreamBuilder() .withStream(contactsFileStream) .withContentType("application/octet-stream") .withLength(contactsFile.length()) @@ -2353,14 +2317,14 @@ public class Manager implements Closeable { } void sendBlockedList() throws IOException, UntrustedIdentityException { - List addresses = new ArrayList<>(); - for (ContactInfo record : account.getContactStore().getContacts()) { + var addresses = new ArrayList(); + for (var record : account.getContactStore().getContacts()) { if (record.blocked) { addresses.add(record.getAddress()); } } - List groupIds = new ArrayList<>(); - for (GroupInfo record : getGroups()) { + var groupIds = new ArrayList(); + for (var record : getGroups()) { if (record.isBlocked()) { groupIds.add(record.getGroupId().serialize()); } @@ -2371,7 +2335,7 @@ public class Manager implements Closeable { private void sendVerifiedMessage( SignalServiceAddress destination, IdentityKey identityKey, TrustLevel trustLevel ) throws IOException, UntrustedIdentityException { - VerifiedMessage verifiedMessage = new VerifiedMessage(destination, + var verifiedMessage = new VerifiedMessage(destination, identityKey, trustLevel.toVerifiedState(), System.currentTimeMillis()); @@ -2383,14 +2347,14 @@ public class Manager implements Closeable { } public String getContactOrProfileName(String number) { - final SignalServiceAddress address = Utils.getSignalServiceAddressFromIdentifier(number); + final var address = Utils.getSignalServiceAddressFromIdentifier(number); - final ContactInfo contact = account.getContactStore().getContact(address); + final var contact = account.getContactStore().getContact(address); if (contact != null && !Util.isEmpty(contact.name)) { return contact.name; } - final SignalProfileEntry profileEntry = account.getProfileStore().getProfileEntry(address); + final var profileEntry = account.getProfileStore().getProfileEntry(address); if (profileEntry != null && profileEntry.getProfile() != null) { return profileEntry.getProfile().getName(); } @@ -2399,9 +2363,9 @@ public class Manager implements Closeable { } public GroupInfo getGroup(GroupId groupId) { - final GroupInfo group = account.getGroupStore().getGroup(groupId); + final var group = account.getGroupStore().getGroup(groupId); if (group instanceof GroupInfoV2 && ((GroupInfoV2) group).getGroup() == null) { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(((GroupInfoV2) group).getMasterKey()); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(((GroupInfoV2) group).getMasterKey()); ((GroupInfoV2) group).setGroup(groupHelper.getDecryptedGroup(groupSecretParams)); account.getGroupStore().updateGroup(group); } @@ -2423,12 +2387,12 @@ public class Manager implements Closeable { * @param fingerprint Fingerprint */ public boolean trustIdentityVerified(String name, byte[] fingerprint) throws InvalidNumberException { - SignalServiceAddress address = canonicalizeAndResolveSignalServiceAddress(name); - List ids = account.getSignalProtocolStore().getIdentities(address); + var address = canonicalizeAndResolveSignalServiceAddress(name); + var ids = account.getSignalProtocolStore().getIdentities(address); if (ids == null) { return false; } - for (IdentityInfo id : ids) { + for (var id : ids) { if (!Arrays.equals(id.getIdentityKey().serialize(), fingerprint)) { continue; } @@ -2453,12 +2417,12 @@ public class Manager implements Closeable { * @param safetyNumber Safety number */ public boolean trustIdentityVerifiedSafetyNumber(String name, String safetyNumber) throws InvalidNumberException { - SignalServiceAddress address = canonicalizeAndResolveSignalServiceAddress(name); - List ids = account.getSignalProtocolStore().getIdentities(address); + var address = canonicalizeAndResolveSignalServiceAddress(name); + var ids = account.getSignalProtocolStore().getIdentities(address); if (ids == null) { return false; } - for (IdentityInfo id : ids) { + for (var id : ids) { if (!safetyNumber.equals(computeSafetyNumber(address, id.getIdentityKey()))) { continue; } @@ -2482,12 +2446,12 @@ public class Manager implements Closeable { * @param name username of the identity */ public boolean trustIdentityAllKeys(String name) { - SignalServiceAddress address = resolveSignalServiceAddress(name); - List ids = account.getSignalProtocolStore().getIdentities(address); + var address = resolveSignalServiceAddress(name); + var ids = account.getSignalProtocolStore().getIdentities(address); if (ids == null) { return false; } - for (IdentityInfo id : ids) { + for (var id : ids) { if (id.getTrustLevel() == TrustLevel.UNTRUSTED) { account.getSignalProtocolStore() .setIdentityTrustLevel(address, id.getIdentityKey(), TrustLevel.TRUSTED_UNVERIFIED); @@ -2513,14 +2477,14 @@ public class Manager implements Closeable { } public SignalServiceAddress canonicalizeAndResolveSignalServiceAddress(String identifier) throws InvalidNumberException { - String canonicalizedNumber = UuidUtil.isUuid(identifier) + var canonicalizedNumber = UuidUtil.isUuid(identifier) ? identifier : PhoneNumberFormatter.formatNumber(identifier, account.getUsername()); return resolveSignalServiceAddress(canonicalizedNumber); } public SignalServiceAddress resolveSignalServiceAddress(String identifier) { - SignalServiceAddress address = Utils.getSignalServiceAddressFromIdentifier(identifier); + var address = Utils.getSignalServiceAddressFromIdentifier(identifier); return resolveSignalServiceAddress(address); } diff --git a/lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java b/lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java index f48ade7c..0ce43bb9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java +++ b/lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java @@ -79,37 +79,30 @@ public class ProvisioningManager { public static ProvisioningManager init( File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent ) { - PathConfig pathConfig = PathConfig.createDefault(settingsPath); + var pathConfig = PathConfig.createDefault(settingsPath); - final ServiceEnvironmentConfig serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig( - serviceEnvironment, - userAgent); + final var serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent); return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent); } public String getDeviceLinkUri() throws TimeoutException, IOException { - String deviceUuid = accountManager.getNewDeviceUuid(); + var deviceUuid = accountManager.getNewDeviceUuid(); return new DeviceLinkInfo(deviceUuid, identityKey.getPublicKey().getPublicKey()).createDeviceLinkUri(); } public String finishDeviceLink(String deviceName) throws IOException, InvalidKeyException, TimeoutException, UserAlreadyExists { - SignalServiceAccountManager.NewDeviceRegistrationReturn ret = accountManager.finishNewDeviceRegistration( - identityKey, - false, - true, - registrationId, - deviceName); + var ret = accountManager.finishNewDeviceRegistration(identityKey, false, true, registrationId, deviceName); - String username = ret.getNumber(); + var username = ret.getNumber(); // TODO do this check before actually registering if (SignalAccount.userExists(pathConfig.getDataPath(), username)) { throw new UserAlreadyExists(username, SignalAccount.getFileName(pathConfig.getDataPath(), username)); } // Create new account with the synced identity - byte[] profileKeyBytes = ret.getProfileKey(); + var profileKeyBytes = ret.getProfileKey(); ProfileKey profileKey; if (profileKeyBytes == null) { profileKey = KeyUtils.createProfileKey(); @@ -121,7 +114,7 @@ public class ProvisioningManager { } } - try (SignalAccount account = SignalAccount.createLinkedAccount(pathConfig.getDataPath(), + try (var account = SignalAccount.createLinkedAccount(pathConfig.getDataPath(), username, ret.getUuid(), password, @@ -131,7 +124,7 @@ public class ProvisioningManager { profileKey)) { account.save(); - try (Manager m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent)) { + try (var m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent)) { try { m.refreshPreKeys(); diff --git a/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java b/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java index baff2047..6ded4d0b 100644 --- a/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java +++ b/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java @@ -22,12 +22,8 @@ import org.asamk.signal.manager.config.ServiceEnvironmentConfig; import org.asamk.signal.manager.helper.PinHelper; import org.asamk.signal.manager.storage.SignalAccount; import org.asamk.signal.manager.util.KeyUtils; -import org.signal.zkgroup.profiles.ProfileKey; -import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.util.KeyHelper; import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.KbsPinData; -import org.whispersystems.signalservice.api.KeyBackupService; import org.whispersystems.signalservice.api.KeyBackupServicePinException; import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException; import org.whispersystems.signalservice.api.SignalServiceAccountManager; @@ -82,7 +78,7 @@ public class RegistrationManager implements Closeable { groupsV2Operations, ServiceConfig.AUTOMATIC_NETWORK_RETRY, timer); - final KeyBackupService keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(), + final var keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(), serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(), serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(), serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(), @@ -93,17 +89,15 @@ public class RegistrationManager implements Closeable { public static RegistrationManager init( String username, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent ) throws IOException { - PathConfig pathConfig = PathConfig.createDefault(settingsPath); + var pathConfig = PathConfig.createDefault(settingsPath); - final ServiceEnvironmentConfig serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig( - serviceEnvironment, - userAgent); + final var serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent); if (!SignalAccount.userExists(pathConfig.getDataPath(), username)) { - IdentityKeyPair identityKey = KeyUtils.generateIdentityKeyPair(); - int registrationId = KeyHelper.generateRegistrationId(false); + var identityKey = KeyUtils.generateIdentityKeyPair(); + var registrationId = KeyHelper.generateRegistrationId(false); - ProfileKey profileKey = KeyUtils.createProfileKey(); - SignalAccount account = SignalAccount.create(pathConfig.getDataPath(), + var profileKey = KeyUtils.createProfileKey(); + var account = SignalAccount.create(pathConfig.getDataPath(), username, identityKey, registrationId, @@ -113,7 +107,7 @@ public class RegistrationManager implements Closeable { return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent); } - SignalAccount account = SignalAccount.load(pathConfig.getDataPath(), username); + var account = SignalAccount.load(pathConfig.getDataPath(), username); return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent); } @@ -147,12 +141,12 @@ public class RegistrationManager implements Closeable { throw e; } - KbsPinData registrationLockData = pinHelper.getRegistrationLockData(pin, e); + var registrationLockData = pinHelper.getRegistrationLockData(pin, e); if (registrationLockData == null) { throw e; } - String registrationLock = registrationLockData.getMasterKey().deriveRegistrationLock(); + var registrationLock = registrationLockData.getMasterKey().deriveRegistrationLock(); try { response = verifyAccountWithCode(verificationCode, null, registrationLock); } catch (LockedException _e) { @@ -175,7 +169,7 @@ public class RegistrationManager implements Closeable { account.getSignalProtocolStore().getIdentityKeyPair().getPublicKey(), TrustLevel.TRUSTED_VERIFIED); - try (Manager m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent)) { + try (var m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent)) { m.refreshPreKeys(); diff --git a/lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java b/lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java index 0b83f53e..4cf86537 100644 --- a/lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java +++ b/lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java @@ -39,7 +39,7 @@ public class ServiceConfig { try { TrustStore contactTrustStore = new IasTrustStore(); - KeyStore keyStore = KeyStore.getInstance("BKS"); + var keyStore = KeyStore.getInstance("BKS"); keyStore.load(contactTrustStore.getKeyStoreInputStream(), contactTrustStore.getKeyStorePassword().toCharArray()); @@ -74,7 +74,7 @@ public class ServiceConfig { .header("User-Agent", userAgent) .build()); - final List interceptors = List.of(userAgentInterceptor); + final var interceptors = List.of(userAgentInterceptor); switch (serviceEnvironment) { case LIVE: diff --git a/lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java b/lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java index 5c5d639c..9ecb9630 100644 --- a/lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java +++ b/lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java @@ -50,7 +50,7 @@ public abstract class GroupId { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final GroupId groupId = (GroupId) o; + final var groupId = (GroupId) o; return Arrays.equals(id, groupId.id); } diff --git a/lib/src/main/java/org/asamk/signal/manager/groups/GroupInviteLinkUrl.java b/lib/src/main/java/org/asamk/signal/manager/groups/GroupInviteLinkUrl.java index bf9e0e55..dd9dd2d2 100644 --- a/lib/src/main/java/org/asamk/signal/manager/groups/GroupInviteLinkUrl.java +++ b/lib/src/main/java/org/asamk/signal/manager/groups/GroupInviteLinkUrl.java @@ -35,7 +35,7 @@ public final class GroupInviteLinkUrl { * @throws InvalidGroupLinkException If group url, but cannot be parsed. */ public static GroupInviteLinkUrl fromUri(String urlString) throws InvalidGroupLinkException, UnknownGroupLinkVersionException { - URI uri = getGroupUrl(urlString); + var uri = getGroupUrl(urlString); if (uri == null) { return null; @@ -46,21 +46,21 @@ public final class GroupInviteLinkUrl { throw new InvalidGroupLinkException("No path was expected in uri"); } - String encoding = uri.getFragment(); + var encoding = uri.getFragment(); if (encoding == null || encoding.length() == 0) { throw new InvalidGroupLinkException("No reference was in the uri"); } - byte[] bytes = Base64UrlSafe.decodePaddingAgnostic(encoding); - GroupInviteLink groupInviteLink = GroupInviteLink.parseFrom(bytes); + var bytes = Base64UrlSafe.decodePaddingAgnostic(encoding); + var groupInviteLink = GroupInviteLink.parseFrom(bytes); switch (groupInviteLink.getContentsCase()) { case V1CONTENTS: { - GroupInviteLink.GroupInviteLinkContentsV1 groupInviteLinkContentsV1 = groupInviteLink.getV1Contents(); - GroupMasterKey groupMasterKey = new GroupMasterKey(groupInviteLinkContentsV1.getGroupMasterKey() + var groupInviteLinkContentsV1 = groupInviteLink.getV1Contents(); + var groupMasterKey = new GroupMasterKey(groupInviteLinkContentsV1.getGroupMasterKey() .toByteArray()); - GroupLinkPassword password = GroupLinkPassword.fromBytes(groupInviteLinkContentsV1.getInviteLinkPassword() + var password = GroupLinkPassword.fromBytes(groupInviteLinkContentsV1.getInviteLinkPassword() .toByteArray()); return new GroupInviteLinkUrl(groupMasterKey, password); @@ -78,7 +78,7 @@ public final class GroupInviteLinkUrl { */ private static URI getGroupUrl(String urlString) { try { - URI url = new URI(urlString); + var url = new URI(urlString); if (!"https".equalsIgnoreCase(url.getScheme()) && !"sgnl".equalsIgnoreCase(url.getScheme())) { return null; @@ -97,13 +97,13 @@ public final class GroupInviteLinkUrl { } protected static String createUrl(GroupMasterKey groupMasterKey, GroupLinkPassword password) { - GroupInviteLink groupInviteLink = GroupInviteLink.newBuilder() + var groupInviteLink = GroupInviteLink.newBuilder() .setV1Contents(GroupInviteLink.GroupInviteLinkContentsV1.newBuilder() .setGroupMasterKey(ByteString.copyFrom(groupMasterKey.serialize())) .setInviteLinkPassword(ByteString.copyFrom(password.serialize()))) .build(); - String encoding = Base64UrlSafe.encodeBytesWithoutPadding(groupInviteLink.toByteArray()); + var encoding = Base64UrlSafe.encodeBytesWithoutPadding(groupInviteLink.toByteArray()); return GROUP_URL_PREFIX + encoding; } diff --git a/lib/src/main/java/org/asamk/signal/manager/groups/GroupUtils.java b/lib/src/main/java/org/asamk/signal/manager/groups/GroupUtils.java index f56639e3..c1db77bf 100644 --- a/lib/src/main/java/org/asamk/signal/manager/groups/GroupUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/groups/GroupUtils.java @@ -18,13 +18,13 @@ public class GroupUtils { final SignalServiceDataMessage.Builder messageBuilder, final GroupInfo groupInfo ) { if (groupInfo instanceof GroupInfoV1) { - SignalServiceGroup group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.DELIVER) + var group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.DELIVER) .withId(groupInfo.getGroupId().serialize()) .build(); messageBuilder.asGroupMessage(group); } else { - final GroupInfoV2 groupInfoV2 = (GroupInfoV2) groupInfo; - SignalServiceGroupV2 group = SignalServiceGroupV2.newBuilder(groupInfoV2.getMasterKey()) + final var groupInfoV2 = (GroupInfoV2) groupInfo; + var group = SignalServiceGroupV2.newBuilder(groupInfoV2.getMasterKey()) .withRevision(groupInfoV2.getGroup() == null ? 0 : groupInfoV2.getGroup().getRevision()) .build(); messageBuilder.asGroupMessage(group); @@ -46,13 +46,12 @@ public class GroupUtils { } public static GroupIdV2 getGroupIdV2(GroupMasterKey groupMasterKey) { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); return getGroupIdV2(groupSecretParams); } public static GroupIdV2 getGroupIdV2(GroupIdV1 groupIdV1) { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(deriveV2MigrationMasterKey( - groupIdV1)); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(deriveV2MigrationMasterKey(groupIdV1)); return getGroupIdV2(groupSecretParams); } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java index d39da8a3..2efc18ad 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -2,7 +2,6 @@ package org.asamk.signal.manager.helper; import com.google.protobuf.InvalidProtocolBufferException; -import org.asamk.signal.manager.groups.GroupIdV2; import org.asamk.signal.manager.groups.GroupLinkPassword; import org.asamk.signal.manager.groups.GroupUtils; import org.asamk.signal.manager.storage.groups.GroupInfoV2; @@ -20,7 +19,6 @@ import org.signal.zkgroup.VerificationFailedException; import org.signal.zkgroup.groups.GroupMasterKey; import org.signal.zkgroup.groups.GroupSecretParams; import org.signal.zkgroup.groups.UuidCiphertext; -import org.signal.zkgroup.profiles.ProfileKeyCredential; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.util.Pair; @@ -41,7 +39,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; -import java.util.List; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -80,7 +77,7 @@ public class GroupHelper { public DecryptedGroup getDecryptedGroup(final GroupSecretParams groupSecretParams) { try { - final GroupsV2AuthorizationString groupsV2AuthorizationString = groupAuthorizationProvider.getAuthorizationForToday( + final var groupsV2AuthorizationString = groupAuthorizationProvider.getAuthorizationForToday( groupSecretParams); return groupsV2Api.getGroup(groupSecretParams, groupsV2AuthorizationString); } catch (IOException | VerificationFailedException | InvalidGroupStateException e) { @@ -92,7 +89,7 @@ public class GroupHelper { public DecryptedGroupJoinInfo getDecryptedGroupJoinInfo( GroupMasterKey groupMasterKey, GroupLinkPassword password ) throws IOException, GroupLinkNotActiveException { - GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); + var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); return groupsV2Api.getGroupJoinInfo(groupSecretParams, Optional.fromNullable(password).transform(GroupLinkPassword::serialize), @@ -102,13 +99,13 @@ public class GroupHelper { public GroupInfoV2 createGroupV2( String name, Collection members, File avatarFile ) throws IOException { - final byte[] avatarBytes = readAvatarBytes(avatarFile); - final GroupsV2Operations.NewGroup newGroup = buildNewGroupV2(name, members, avatarBytes); + final var avatarBytes = readAvatarBytes(avatarFile); + final var newGroup = buildNewGroupV2(name, members, avatarBytes); if (newGroup == null) { return null; } - final GroupSecretParams groupSecretParams = newGroup.getGroupSecretParams(); + final var groupSecretParams = newGroup.getGroupSecretParams(); final GroupsV2AuthorizationString groupAuthForToday; final DecryptedGroup decryptedGroup; @@ -125,9 +122,9 @@ public class GroupHelper { return null; } - final GroupIdV2 groupId = GroupUtils.getGroupIdV2(groupSecretParams); - final GroupMasterKey masterKey = groupSecretParams.getMasterKey(); - GroupInfoV2 g = new GroupInfoV2(groupId, masterKey); + final var groupId = GroupUtils.getGroupIdV2(groupSecretParams); + final var masterKey = groupSecretParams.getMasterKey(); + var g = new GroupInfoV2(groupId, masterKey); g.setGroup(decryptedGroup); return g; @@ -144,8 +141,7 @@ public class GroupHelper { private GroupsV2Operations.NewGroup buildNewGroupV2( String name, Collection members, byte[] avatar ) { - final ProfileKeyCredential profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential( - selfAddressProvider.getSelfAddress()); + final var profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential(selfAddressProvider.getSelfAddress()); if (profileKeyCredential == null) { logger.warn("Cannot create a V2 group as self does not have a versioned profile"); return null; @@ -153,14 +149,14 @@ public class GroupHelper { if (!areMembersValid(members)) return null; - GroupCandidate self = new GroupCandidate(selfAddressProvider.getSelfAddress().getUuid().orNull(), + var self = new GroupCandidate(selfAddressProvider.getSelfAddress().getUuid().orNull(), Optional.fromNullable(profileKeyCredential)); - Set candidates = members.stream() + var candidates = members.stream() .map(member -> new GroupCandidate(member.getUuid().get(), Optional.fromNullable(profileKeyCredentialProvider.getProfileKeyCredential(member)))) .collect(Collectors.toSet()); - final GroupSecretParams groupSecretParams = GroupSecretParams.generate(); + final var groupSecretParams = GroupSecretParams.generate(); return groupsV2Operations.createNewGroup(groupSecretParams, name, Optional.fromNullable(avatar), @@ -171,7 +167,7 @@ public class GroupHelper { } private boolean areMembersValid(final Collection members) { - final Set noUuidCapability = members.stream() + final var noUuidCapability = members.stream() .filter(address -> !address.getUuid().isPresent()) .map(SignalServiceAddress::getLegacyIdentifier) .collect(Collectors.toSet()); @@ -181,7 +177,7 @@ public class GroupHelper { return false; } - final Set noGv2Capability = members.stream() + final var noGv2Capability = members.stream() .map(profileProvider::getProfile) .filter(profile -> profile != null && !profile.getCapabilities().gv2) .collect(Collectors.toSet()); @@ -197,22 +193,20 @@ public class GroupHelper { public Pair updateGroupV2( GroupInfoV2 groupInfoV2, String name, File avatarFile ) throws IOException { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); - GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); + var groupOperations = groupsV2Operations.forGroup(groupSecretParams); - GroupChange.Actions.Builder change = name != null - ? groupOperations.createModifyGroupTitle(name) - : GroupChange.Actions.newBuilder(); + var change = name != null ? groupOperations.createModifyGroupTitle(name) : GroupChange.Actions.newBuilder(); if (avatarFile != null) { - final byte[] avatarBytes = readAvatarBytes(avatarFile); - String avatarCdnKey = groupsV2Api.uploadAvatar(avatarBytes, + final var avatarBytes = readAvatarBytes(avatarFile); + var avatarCdnKey = groupsV2Api.uploadAvatar(avatarBytes, groupSecretParams, groupAuthorizationProvider.getAuthorizationForToday(groupSecretParams)); change.setModifyAvatar(GroupChange.Actions.ModifyAvatarAction.newBuilder().setAvatar(avatarCdnKey)); } - final Optional uuid = this.selfAddressProvider.getSelfAddress().getUuid(); + final var uuid = this.selfAddressProvider.getSelfAddress().getUuid(); if (uuid.isPresent()) { change.setSourceUuid(UuidUtil.toByteString(uuid.get())); } @@ -223,22 +217,22 @@ public class GroupHelper { public Pair updateGroupV2( GroupInfoV2 groupInfoV2, Set newMembers ) throws IOException { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); - GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); + var groupOperations = groupsV2Operations.forGroup(groupSecretParams); if (!areMembersValid(newMembers)) { throw new IOException("Failed to update group"); } - Set candidates = newMembers.stream() + var candidates = newMembers.stream() .map(member -> new GroupCandidate(member.getUuid().get(), Optional.fromNullable(profileKeyCredentialProvider.getProfileKeyCredential(member)))) .collect(Collectors.toSet()); - final GroupChange.Actions.Builder change = groupOperations.createModifyGroupMembershipChange(candidates, + final var change = groupOperations.createModifyGroupMembershipChange(candidates, selfAddressProvider.getSelfAddress().getUuid().get()); - final Optional uuid = this.selfAddressProvider.getSelfAddress().getUuid(); + final var uuid = this.selfAddressProvider.getSelfAddress().getUuid(); if (uuid.isPresent()) { change.setSourceUuid(UuidUtil.toByteString(uuid.get())); } @@ -247,10 +241,9 @@ public class GroupHelper { } public Pair leaveGroup(GroupInfoV2 groupInfoV2) throws IOException { - List pendingMembersList = groupInfoV2.getGroup().getPendingMembersList(); - final UUID selfUuid = selfAddressProvider.getSelfAddress().getUuid().get(); - Optional selfPendingMember = DecryptedGroupUtil.findPendingByUuid(pendingMembersList, - selfUuid); + var pendingMembersList = groupInfoV2.getGroup().getPendingMembersList(); + final var selfUuid = selfAddressProvider.getSelfAddress().getUuid().get(); + var selfPendingMember = DecryptedGroupUtil.findPendingByUuid(pendingMembersList, selfUuid); if (selfPendingMember.isPresent()) { return revokeInvites(groupInfoV2, Set.of(selfPendingMember.get())); @@ -264,19 +257,17 @@ public class GroupHelper { GroupLinkPassword groupLinkPassword, DecryptedGroupJoinInfo decryptedGroupJoinInfo ) throws IOException { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); - final GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); + final var groupOperations = groupsV2Operations.forGroup(groupSecretParams); - final SignalServiceAddress selfAddress = this.selfAddressProvider.getSelfAddress(); - final ProfileKeyCredential profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential( - selfAddress); + final var selfAddress = this.selfAddressProvider.getSelfAddress(); + final var profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential(selfAddress); if (profileKeyCredential == null) { throw new IOException("Cannot join a V2 group as self does not have a versioned profile"); } - boolean requestToJoin = decryptedGroupJoinInfo.getAddFromInviteLink() - == AccessControl.AccessRequired.ADMINISTRATOR; - GroupChange.Actions.Builder change = requestToJoin + var requestToJoin = decryptedGroupJoinInfo.getAddFromInviteLink() == AccessControl.AccessRequired.ADMINISTRATOR; + var change = requestToJoin ? groupOperations.createGroupJoinRequest(profileKeyCredential) : groupOperations.createGroupJoinDirect(profileKeyCredential); @@ -286,19 +277,18 @@ public class GroupHelper { } public Pair acceptInvite(GroupInfoV2 groupInfoV2) throws IOException { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); - final GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); + final var groupOperations = groupsV2Operations.forGroup(groupSecretParams); - final SignalServiceAddress selfAddress = this.selfAddressProvider.getSelfAddress(); - final ProfileKeyCredential profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential( - selfAddress); + final var selfAddress = this.selfAddressProvider.getSelfAddress(); + final var profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential(selfAddress); if (profileKeyCredential == null) { throw new IOException("Cannot join a V2 group as self does not have a versioned profile"); } - final GroupChange.Actions.Builder change = groupOperations.createAcceptInviteChange(profileKeyCredential); + final var change = groupOperations.createAcceptInviteChange(profileKeyCredential); - final Optional uuid = selfAddress.getUuid(); + final var uuid = selfAddress.getUuid(); if (uuid.isPresent()) { change.setSourceUuid(UuidUtil.toByteString(uuid.get())); } @@ -309,9 +299,9 @@ public class GroupHelper { public Pair revokeInvites( GroupInfoV2 groupInfoV2, Set pendingMembers ) throws IOException { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); - final GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); - final Set uuidCipherTexts = pendingMembers.stream().map(member -> { + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); + final var groupOperations = groupsV2Operations.forGroup(groupSecretParams); + final var uuidCipherTexts = pendingMembers.stream().map(member -> { try { return new UuidCiphertext(member.getUuidCipherText().toByteArray()); } catch (InvalidInputException e) { @@ -322,19 +312,19 @@ public class GroupHelper { } public Pair ejectMembers(GroupInfoV2 groupInfoV2, Set uuids) throws IOException { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); - final GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); + final var groupOperations = groupsV2Operations.forGroup(groupSecretParams); return commitChange(groupInfoV2, groupOperations.createRemoveMembersChange(uuids)); } private Pair commitChange( GroupInfoV2 groupInfoV2, GroupChange.Actions.Builder change ) throws IOException { - final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); - final GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); - final DecryptedGroup previousGroupState = groupInfoV2.getGroup(); - final int nextRevision = previousGroupState.getRevision() + 1; - final GroupChange.Actions changeActions = change.setRevision(nextRevision).build(); + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); + final var groupOperations = groupsV2Operations.forGroup(groupSecretParams); + final var previousGroupState = groupInfoV2.getGroup(); + final var nextRevision = previousGroupState.getRevision() + 1; + final var changeActions = change.setRevision(nextRevision).build(); final DecryptedGroupChange decryptedChange; final DecryptedGroup decryptedGroupState; @@ -346,7 +336,7 @@ public class GroupHelper { throw new IOException(e); } - GroupChange signedGroupChange = groupsV2Api.patchGroup(changeActions, + var signedGroupChange = groupsV2Api.patchGroup(changeActions, groupAuthorizationProvider.getAuthorizationForToday(groupSecretParams), Optional.absent()); @@ -359,8 +349,8 @@ public class GroupHelper { GroupChange.Actions.Builder change, GroupLinkPassword password ) throws IOException { - final int nextRevision = currentRevision + 1; - final GroupChange.Actions changeActions = change.setRevision(nextRevision).build(); + final var nextRevision = currentRevision + 1; + final var changeActions = change.setRevision(nextRevision).build(); return groupsV2Api.patchGroup(changeActions, groupAuthorizationProvider.getAuthorizationForToday(groupSecretParams), @@ -371,8 +361,7 @@ public class GroupHelper { DecryptedGroup group, byte[] signedGroupChange, GroupMasterKey groupMasterKey ) { try { - final DecryptedGroupChange decryptedGroupChange = getDecryptedGroupChange(signedGroupChange, - groupMasterKey); + final var decryptedGroupChange = getDecryptedGroupChange(signedGroupChange, groupMasterKey); if (decryptedGroupChange == null) { return null; } @@ -384,8 +373,7 @@ public class GroupHelper { private DecryptedGroupChange getDecryptedGroupChange(byte[] signedGroupChange, GroupMasterKey groupMasterKey) { if (signedGroupChange != null) { - GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(GroupSecretParams.deriveFromMasterKey( - groupMasterKey)); + var groupOperations = groupsV2Operations.forGroup(GroupSecretParams.deriveFromMasterKey(groupMasterKey)); try { return groupOperations.decryptChange(GroupChange.parseFrom(signedGroupChange), true).orNull(); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java index 090b20b6..cf98c4c9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java @@ -6,7 +6,6 @@ import org.whispersystems.signalservice.api.KbsPinData; import org.whispersystems.signalservice.api.KeyBackupService; import org.whispersystems.signalservice.api.KeyBackupServicePinException; import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException; -import org.whispersystems.signalservice.api.kbs.HashedPin; import org.whispersystems.signalservice.api.kbs.MasterKey; import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException; import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse; @@ -25,15 +24,15 @@ public class PinHelper { public void setRegistrationLockPin( String pin, MasterKey masterKey ) throws IOException, UnauthenticatedResponseException { - final KeyBackupService.PinChangeSession pinChangeSession = keyBackupService.newPinChangeSession(); - final HashedPin hashedPin = PinHashing.hashPin(pin, pinChangeSession); + final var pinChangeSession = keyBackupService.newPinChangeSession(); + final var hashedPin = PinHashing.hashPin(pin, pinChangeSession); pinChangeSession.setPin(hashedPin, masterKey); pinChangeSession.enableRegistrationLock(masterKey); } public void removeRegistrationLockPin() throws IOException, UnauthenticatedResponseException { - final KeyBackupService.PinChangeSession pinChangeSession = keyBackupService.newPinChangeSession(); + final var pinChangeSession = keyBackupService.newPinChangeSession(); pinChangeSession.disableRegistrationLock(); pinChangeSession.removePin(); } @@ -41,7 +40,7 @@ public class PinHelper { public KbsPinData getRegistrationLockData( String pin, LockedException e ) throws IOException, KeyBackupSystemNoDataException, KeyBackupServicePinException { - String basicStorageCredentials = e.getBasicStorageCredentials(); + var basicStorageCredentials = e.getBasicStorageCredentials(); if (basicStorageCredentials == null) { return null; } @@ -52,12 +51,12 @@ public class PinHelper { private KbsPinData getRegistrationLockData( String pin, String basicStorageCredentials ) throws IOException, KeyBackupSystemNoDataException, KeyBackupServicePinException { - TokenResponse tokenResponse = keyBackupService.getToken(basicStorageCredentials); + var tokenResponse = keyBackupService.getToken(basicStorageCredentials); if (tokenResponse == null || tokenResponse.getTries() == 0) { throw new IOException("KBS Account locked"); } - KbsPinData registrationLockData = restoreMasterKey(pin, basicStorageCredentials, tokenResponse); + var registrationLockData = restoreMasterKey(pin, basicStorageCredentials, tokenResponse); if (registrationLockData == null) { throw new AssertionError("Failed to restore master key"); } @@ -73,12 +72,11 @@ public class PinHelper { throw new AssertionError("Cannot restore KBS key, no storage credentials supplied"); } - KeyBackupService.RestoreSession session = keyBackupService.newRegistrationSession(basicStorageCredentials, - tokenResponse); + var session = keyBackupService.newRegistrationSession(basicStorageCredentials, tokenResponse); try { - HashedPin hashedPin = PinHashing.hashPin(pin, session); - KbsPinData kbsData = session.restorePin(hashedPin); + var hashedPin = PinHashing.hashPin(pin, session); + var kbsData = session.restorePin(hashedPin); if (kbsData == null) { throw new AssertionError("Null not expected"); } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java index 60c47d8b..5411bb06 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java @@ -2,10 +2,7 @@ package org.asamk.signal.manager.helper; import org.signal.zkgroup.profiles.ProfileKey; import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.SignalServiceMessagePipe; -import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess; -import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.SignalServiceAddress; @@ -63,8 +60,8 @@ public final class ProfileHelper { public ListenableFuture retrieveProfile( SignalServiceAddress address, SignalServiceProfile.RequestType requestType ) { - Optional unidentifiedAccess = getUnidentifiedAccess(address); - Optional profileKey = Optional.fromNullable(profileKeyProvider.getProfileKey(address)); + var unidentifiedAccess = getUnidentifiedAccess(address); + var profileKey = Optional.fromNullable(profileKeyProvider.getProfileKey(address)); if (unidentifiedAccess.isPresent()) { return new CascadingFuture<>(Arrays.asList(() -> getPipeRetrievalFuture(address, @@ -90,8 +87,8 @@ public final class ProfileHelper { Optional unidentifiedAccess, SignalServiceProfile.RequestType requestType ) throws IOException { - SignalServiceMessagePipe unidentifiedPipe = messagePipeProvider.getMessagePipe(true); - SignalServiceMessagePipe pipe = unidentifiedPipe != null && unidentifiedAccess.isPresent() + var unidentifiedPipe = messagePipeProvider.getMessagePipe(true); + var pipe = unidentifiedPipe != null && unidentifiedAccess.isPresent() ? unidentifiedPipe : messagePipeProvider.getMessagePipe(false); if (pipe != null) { @@ -102,8 +99,7 @@ public final class ProfileHelper { if (!address.getNumber().isPresent()) { throw new NotFoundException("Can't request profile without number"); } - SignalServiceAddress addressWithoutUuid = new SignalServiceAddress(Optional.absent(), - address.getNumber()); + var addressWithoutUuid = new SignalServiceAddress(Optional.absent(), address.getNumber()); return pipe.getProfile(addressWithoutUuid, profileKey, unidentifiedAccess, requestType); } } @@ -117,7 +113,7 @@ public final class ProfileHelper { Optional unidentifiedAccess, SignalServiceProfile.RequestType requestType ) throws NotFoundException { - SignalServiceMessageReceiver receiver = messageReceiverProvider.getMessageReceiver(); + var receiver = messageReceiverProvider.getMessageReceiver(); try { return receiver.retrieveProfile(address, profileKey, unidentifiedAccess, requestType); } catch (NoClassDefFoundError e) { @@ -125,13 +121,13 @@ public final class ProfileHelper { if (!address.getNumber().isPresent()) { throw new NotFoundException("Can't request profile without number"); } - SignalServiceAddress addressWithoutUuid = new SignalServiceAddress(Optional.absent(), address.getNumber()); + var addressWithoutUuid = new SignalServiceAddress(Optional.absent(), address.getNumber()); return receiver.retrieveProfile(addressWithoutUuid, profileKey, unidentifiedAccess, requestType); } } private Optional getUnidentifiedAccess(SignalServiceAddress recipient) { - Optional unidentifiedAccess = unidentifiedAccessProvider.getAccessFor(recipient); + var unidentifiedAccess = unidentifiedAccessProvider.getAccessFor(recipient); if (unidentifiedAccess.isPresent()) { return unidentifiedAccess.get().getTargetUnidentifiedAccess(); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java index 3930154c..a3b8e3b5 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java @@ -1,8 +1,6 @@ package org.asamk.signal.manager.helper; -import org.asamk.signal.manager.storage.profiles.SignalProfile; import org.signal.libsignal.metadata.certificate.InvalidCertificateException; -import org.signal.zkgroup.profiles.ProfileKey; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair; @@ -41,12 +39,12 @@ public class UnidentifiedAccessHelper { } public byte[] getTargetUnidentifiedAccessKey(SignalServiceAddress recipient) { - ProfileKey theirProfileKey = profileKeyProvider.getProfileKey(recipient); + var theirProfileKey = profileKeyProvider.getProfileKey(recipient); if (theirProfileKey == null) { return null; } - SignalProfile targetProfile = profileProvider.getProfile(recipient); + var targetProfile = profileProvider.getProfile(recipient); if (targetProfile == null || targetProfile.getUnidentifiedAccess() == null) { return null; } @@ -59,8 +57,8 @@ public class UnidentifiedAccessHelper { } public Optional getAccessForSync() { - byte[] selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(); - byte[] selfUnidentifiedAccessCertificate = senderCertificateProvider.getSenderCertificate(); + var selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(); + var selfUnidentifiedAccessCertificate = senderCertificateProvider.getSenderCertificate(); if (selfUnidentifiedAccessKey == null || selfUnidentifiedAccessCertificate == null) { return Optional.absent(); @@ -80,9 +78,9 @@ public class UnidentifiedAccessHelper { } public Optional getAccessFor(SignalServiceAddress recipient) { - byte[] recipientUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipient); - byte[] selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(); - byte[] selfUnidentifiedAccessCertificate = senderCertificateProvider.getSenderCertificate(); + var recipientUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipient); + var selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(); + var selfUnidentifiedAccessCertificate = senderCertificateProvider.getSenderCertificate(); if (recipientUnidentifiedAccessKey == null || selfUnidentifiedAccessKey == null diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java index bac42733..d4e2a253 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java @@ -8,24 +8,18 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.node.ObjectNode; import org.asamk.signal.manager.groups.GroupId; -import org.asamk.signal.manager.storage.contacts.ContactInfo; import org.asamk.signal.manager.storage.contacts.JsonContactsStore; -import org.asamk.signal.manager.storage.groups.GroupInfo; import org.asamk.signal.manager.storage.groups.GroupInfoV1; import org.asamk.signal.manager.storage.groups.JsonGroupStore; import org.asamk.signal.manager.storage.messageCache.MessageCache; import org.asamk.signal.manager.storage.profiles.ProfileStore; -import org.asamk.signal.manager.storage.protocol.IdentityInfo; import org.asamk.signal.manager.storage.protocol.JsonSignalProtocolStore; import org.asamk.signal.manager.storage.protocol.RecipientStore; -import org.asamk.signal.manager.storage.protocol.SessionInfo; import org.asamk.signal.manager.storage.protocol.SignalServiceAddressResolver; import org.asamk.signal.manager.storage.stickers.StickerStore; import org.asamk.signal.manager.storage.threads.LegacyJsonThreadStore; -import org.asamk.signal.manager.storage.threads.ThreadInfo; import org.asamk.signal.manager.util.IOUtils; import org.asamk.signal.manager.util.KeyUtils; import org.asamk.signal.manager.util.Utils; @@ -99,10 +93,10 @@ public class SignalAccount implements Closeable { } public static SignalAccount load(File dataPath, String username) throws IOException { - final File fileName = getFileName(dataPath, username); - final Pair pair = openFileChannel(fileName); + final var fileName = getFileName(dataPath, username); + final var pair = openFileChannel(fileName); try { - SignalAccount account = new SignalAccount(pair.first(), pair.second()); + var account = new SignalAccount(pair.first(), pair.second()); account.load(dataPath); account.migrateLegacyConfigs(); @@ -118,13 +112,13 @@ public class SignalAccount implements Closeable { File dataPath, String username, IdentityKeyPair identityKey, int registrationId, ProfileKey profileKey ) throws IOException { IOUtils.createPrivateDirectories(dataPath); - File fileName = getFileName(dataPath, username); + var fileName = getFileName(dataPath, username); if (!fileName.exists()) { IOUtils.createPrivateFile(fileName); } - final Pair pair = openFileChannel(fileName); - SignalAccount account = new SignalAccount(pair.first(), pair.second()); + final var pair = openFileChannel(fileName); + var account = new SignalAccount(pair.first(), pair.second()); account.username = username; account.profileKey = profileKey; @@ -155,13 +149,13 @@ public class SignalAccount implements Closeable { ProfileKey profileKey ) throws IOException { IOUtils.createPrivateDirectories(dataPath); - File fileName = getFileName(dataPath, username); + var fileName = getFileName(dataPath, username); if (!fileName.exists()) { IOUtils.createPrivateFile(fileName); } - final Pair pair = openFileChannel(fileName); - SignalAccount account = new SignalAccount(pair.first(), pair.second()); + final var pair = openFileChannel(fileName); + var account = new SignalAccount(pair.first(), pair.second()); account.username = username; account.uuid = uuid; @@ -192,8 +186,8 @@ public class SignalAccount implements Closeable { save(); } // Store profile keys only in profile store - for (ContactInfo contact : getContactStore().getContacts()) { - String profileKeyString = contact.profileKey; + for (var contact : getContactStore().getContacts()) { + var profileKeyString = contact.profileKey; if (profileKeyString == null) { continue; } @@ -230,7 +224,7 @@ public class SignalAccount implements Closeable { if (username == null) { return false; } - File f = getFileName(dataPath, username); + var f = getFileName(dataPath, username); return !(!f.exists() || f.isDirectory()); } @@ -288,7 +282,7 @@ public class SignalAccount implements Closeable { signalProtocolStore = jsonProcessor.convertValue(Utils.getNotNullNode(rootNode, "axolotlStore"), JsonSignalProtocolStore.class); registered = Utils.getNotNullNode(rootNode, "registered").asBoolean(); - JsonNode groupStoreNode = rootNode.get("groupStore"); + var groupStoreNode = rootNode.get("groupStore"); if (groupStoreNode != null) { groupStore = jsonProcessor.convertValue(groupStoreNode, JsonGroupStore.class); groupStore.groupCachePath = getGroupCachePath(dataPath, username); @@ -297,7 +291,7 @@ public class SignalAccount implements Closeable { groupStore = new JsonGroupStore(getGroupCachePath(dataPath, username)); } - JsonNode contactStoreNode = rootNode.get("contactStore"); + var contactStoreNode = rootNode.get("contactStore"); if (contactStoreNode != null) { contactStore = jsonProcessor.convertValue(contactStoreNode, JsonContactsStore.class); } @@ -305,7 +299,7 @@ public class SignalAccount implements Closeable { contactStore = new JsonContactsStore(); } - JsonNode recipientStoreNode = rootNode.get("recipientStore"); + var recipientStoreNode = rootNode.get("recipientStore"); if (recipientStoreNode != null) { recipientStore = jsonProcessor.convertValue(recipientStoreNode, RecipientStore.class); } @@ -314,29 +308,29 @@ public class SignalAccount implements Closeable { recipientStore.resolveServiceAddress(getSelfAddress()); - for (ContactInfo contact : contactStore.getContacts()) { + for (var contact : contactStore.getContacts()) { recipientStore.resolveServiceAddress(contact.getAddress()); } - for (GroupInfo group : groupStore.getGroups()) { + for (var group : groupStore.getGroups()) { if (group instanceof GroupInfoV1) { - GroupInfoV1 groupInfoV1 = (GroupInfoV1) group; + var groupInfoV1 = (GroupInfoV1) group; groupInfoV1.members = groupInfoV1.members.stream() .map(m -> recipientStore.resolveServiceAddress(m)) .collect(Collectors.toSet()); } } - for (SessionInfo session : signalProtocolStore.getSessions()) { + for (var session : signalProtocolStore.getSessions()) { session.address = recipientStore.resolveServiceAddress(session.address); } - for (IdentityInfo identity : signalProtocolStore.getIdentities()) { + for (var identity : signalProtocolStore.getIdentities()) { identity.setAddress(recipientStore.resolveServiceAddress(identity.getAddress())); } } - JsonNode profileStoreNode = rootNode.get("profileStore"); + var profileStoreNode = rootNode.get("profileStore"); if (profileStoreNode != null) { profileStore = jsonProcessor.convertValue(profileStoreNode, ProfileStore.class); } @@ -344,7 +338,7 @@ public class SignalAccount implements Closeable { profileStore = new ProfileStore(); } - JsonNode stickerStoreNode = rootNode.get("stickerStore"); + var stickerStoreNode = rootNode.get("stickerStore"); if (stickerStoreNode != null) { stickerStore = jsonProcessor.convertValue(stickerStoreNode, StickerStore.class); } @@ -354,22 +348,21 @@ public class SignalAccount implements Closeable { messageCache = new MessageCache(getMessageCachePath(dataPath, username)); - JsonNode threadStoreNode = rootNode.get("threadStore"); + var threadStoreNode = rootNode.get("threadStore"); if (threadStoreNode != null && !threadStoreNode.isNull()) { - LegacyJsonThreadStore threadStore = jsonProcessor.convertValue(threadStoreNode, - LegacyJsonThreadStore.class); + var threadStore = jsonProcessor.convertValue(threadStoreNode, LegacyJsonThreadStore.class); // Migrate thread info to group and contact store - for (ThreadInfo thread : threadStore.getThreads()) { + for (var thread : threadStore.getThreads()) { if (thread.id == null || thread.id.isEmpty()) { continue; } try { - ContactInfo contactInfo = contactStore.getContact(new SignalServiceAddress(null, thread.id)); + var contactInfo = contactStore.getContact(new SignalServiceAddress(null, thread.id)); if (contactInfo != null) { contactInfo.messageExpirationTime = thread.messageExpirationTime; contactStore.updateContact(contactInfo); } else { - GroupInfo groupInfo = groupStore.getGroup(GroupId.fromBase64(thread.id)); + var groupInfo = groupStore.getGroup(GroupId.fromBase64(thread.id)); if (groupInfo instanceof GroupInfoV1) { ((GroupInfoV1) groupInfo).messageExpirationTime = thread.messageExpirationTime; groupStore.updateGroup(groupInfo); @@ -385,7 +378,7 @@ public class SignalAccount implements Closeable { if (fileChannel == null) { return; } - ObjectNode rootNode = jsonProcessor.createObjectNode(); + var rootNode = jsonProcessor.createObjectNode(); rootNode.put("username", username) .put("uuid", uuid == null ? null : uuid.toString()) .put("deviceId", deviceId) @@ -407,10 +400,10 @@ public class SignalAccount implements Closeable { .putPOJO("profileStore", profileStore) .putPOJO("stickerStore", stickerStore); try { - try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { + try (var output = new ByteArrayOutputStream()) { // Write to memory first to prevent corrupting the file in case of serialization errors jsonProcessor.writeValue(output, rootNode); - ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); + var input = new ByteArrayInputStream(output.toByteArray()); synchronized (fileChannel) { fileChannel.position(0); input.transferTo(Channels.newOutputStream(fileChannel)); @@ -424,8 +417,8 @@ public class SignalAccount implements Closeable { } private static Pair openFileChannel(File fileName) throws IOException { - FileChannel fileChannel = new RandomAccessFile(fileName, "rw").getChannel(); - FileLock lock = fileChannel.tryLock(); + var fileChannel = new RandomAccessFile(fileName, "rw").getChannel(); + var lock = fileChannel.tryLock(); if (lock == null) { logger.info("Config file is in use by another instance, waiting…"); lock = fileChannel.lock(); @@ -439,7 +432,7 @@ public class SignalAccount implements Closeable { } public void addPreKeys(Collection records) { - for (PreKeyRecord record : records) { + for (var record : records) { signalProtocolStore.storePreKey(record.getId(), record); } preKeyIdOffset = (preKeyIdOffset + records.size()) % Medium.MAX_VALUE; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/contacts/JsonContactsStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/contacts/JsonContactsStore.java index d2859f3f..b80dfe95 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/contacts/JsonContactsStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/contacts/JsonContactsStore.java @@ -13,8 +13,8 @@ public class JsonContactsStore { private List contacts = new ArrayList<>(); public void updateContact(ContactInfo contact) { - final SignalServiceAddress contactAddress = contact.getAddress(); - for (int i = 0; i < contacts.size(); i++) { + final var contactAddress = contact.getAddress(); + for (var i = 0; i < contacts.size(); i++) { if (contacts.get(i).getAddress().matches(contactAddress)) { contacts.set(i, contact); return; @@ -25,7 +25,7 @@ public class JsonContactsStore { } public ContactInfo getContact(SignalServiceAddress address) { - for (ContactInfo contact : contacts) { + for (var contact : contacts) { if (contact.getAddress().matches(address)) { if (contact.uuid == null) { contact.uuid = address.getUuid().orNull(); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfo.java b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfo.java index a644b620..68af2b80 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfo.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfo.java @@ -57,7 +57,7 @@ public abstract class GroupInfo { @JsonIgnore public boolean isMember(SignalServiceAddress address) { - for (SignalServiceAddress member : getMembers()) { + for (var member : getMembers()) { if (member.matches(address)) { return true; } @@ -67,7 +67,7 @@ public abstract class GroupInfo { @JsonIgnore public boolean isPendingMember(SignalServiceAddress address) { - for (SignalServiceAddress member : getPendingMembers()) { + for (var member : getPendingMembers()) { if (member.matches(address)) { return true; } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV1.java b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV1.java index d1230b27..970ec5c3 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV1.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV1.java @@ -135,7 +135,7 @@ public class GroupInfoV1 extends GroupInfo { } public void addMembers(Collection addresses) { - for (SignalServiceAddress address : addresses) { + for (var address : addresses) { if (this.members.contains(address)) { continue; } @@ -178,7 +178,7 @@ public class GroupInfoV1 extends GroupInfo { final Set value, final JsonGenerator jgen, final SerializerProvider provider ) throws IOException { jgen.writeStartArray(value.size()); - for (SignalServiceAddress address : value) { + for (var address : value) { if (address.getUuid().isPresent()) { jgen.writeObject(new JsonSignalServiceAddress(address)); } else { @@ -195,13 +195,13 @@ public class GroupInfoV1 extends GroupInfo { public Set deserialize( JsonParser jsonParser, DeserializationContext deserializationContext ) throws IOException { - Set addresses = new HashSet<>(); + var addresses = new HashSet(); JsonNode node = jsonParser.getCodec().readTree(jsonParser); - for (JsonNode n : node) { + for (var n : node) { if (n.isTextual()) { addresses.add(new SignalServiceAddress(null, n.textValue())); } else { - JsonSignalServiceAddress address = jsonProcessor.treeToValue(n, JsonSignalServiceAddress.class); + var address = jsonProcessor.treeToValue(n, JsonSignalServiceAddress.class); addresses.add(address.toSignalServiceAddress()); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/groups/JsonGroupStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/groups/JsonGroupStore.java index 52b789c7..8e37895a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/groups/JsonGroupStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/groups/JsonGroupStore.java @@ -30,7 +30,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Base64; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -59,10 +58,10 @@ public class JsonGroupStore { if (group instanceof GroupInfoV2 && ((GroupInfoV2) group).getGroup() != null) { try { IOUtils.createPrivateDirectories(groupCachePath); - try (FileOutputStream stream = new FileOutputStream(getGroupFile(group.getGroupId()))) { + try (var stream = new FileOutputStream(getGroupFile(group.getGroupId()))) { ((GroupInfoV2) group).getGroup().writeTo(stream); } - final File groupFileLegacy = getGroupFileLegacy(group.getGroupId()); + final var groupFileLegacy = getGroupFileLegacy(group.getGroupId()); if (groupFileLegacy.exists()) { groupFileLegacy.delete(); } @@ -77,7 +76,7 @@ public class JsonGroupStore { } public GroupInfo getGroup(GroupId groupId) { - GroupInfo group = groups.get(groupId); + var group = groups.get(groupId); if (group == null) { if (groupId instanceof GroupIdV1) { group = groups.get(GroupUtils.getGroupIdV2((GroupIdV1) groupId)); @@ -90,9 +89,9 @@ public class JsonGroupStore { } private GroupInfoV1 getGroupV1ByV2Id(GroupIdV2 groupIdV2) { - for (GroupInfo g : groups.values()) { + for (var g : groups.values()) { if (g instanceof GroupInfoV1) { - final GroupInfoV1 gv1 = (GroupInfoV1) g; + final var gv1 = (GroupInfoV1) g; if (groupIdV2.equals(gv1.getExpectedV2Id())) { return gv1; } @@ -103,14 +102,14 @@ public class JsonGroupStore { private void loadDecryptedGroup(final GroupInfo group) { if (group instanceof GroupInfoV2 && ((GroupInfoV2) group).getGroup() == null) { - File groupFile = getGroupFile(group.getGroupId()); + var groupFile = getGroupFile(group.getGroupId()); if (!groupFile.exists()) { groupFile = getGroupFileLegacy(group.getGroupId()); } if (!groupFile.exists()) { return; } - try (FileInputStream stream = new FileInputStream(groupFile)) { + try (var stream = new FileInputStream(groupFile)) { ((GroupInfoV2) group).setGroup(DecryptedGroup.parseFrom(stream)); } catch (IOException ignored) { } @@ -126,7 +125,7 @@ public class JsonGroupStore { } public GroupInfoV1 getOrCreateGroupV1(GroupIdV1 groupId) { - GroupInfo group = getGroup(groupId); + var group = getGroup(groupId); if (group instanceof GroupInfoV1) { return (GroupInfoV1) group; } @@ -139,8 +138,8 @@ public class JsonGroupStore { } public List getGroups() { - final Collection groups = this.groups.values(); - for (GroupInfo group : groups) { + final var groups = this.groups.values(); + for (var group : groups) { loadDecryptedGroup(group); } return new ArrayList<>(groups); @@ -152,13 +151,13 @@ public class JsonGroupStore { public void serialize( final Map value, final JsonGenerator jgen, final SerializerProvider provider ) throws IOException { - final Collection groups = value.values(); + final var groups = value.values(); jgen.writeStartArray(groups.size()); - for (GroupInfo group : groups) { + for (var group : groups) { if (group instanceof GroupInfoV1) { jgen.writeObject(group); } else if (group instanceof GroupInfoV2) { - final GroupInfoV2 groupV2 = (GroupInfoV2) group; + final var groupV2 = (GroupInfoV2) group; jgen.writeStartObject(); jgen.writeStringField("groupId", groupV2.getGroupId().toBase64()); jgen.writeStringField("masterKey", @@ -179,16 +178,15 @@ public class JsonGroupStore { public Map deserialize( JsonParser jsonParser, DeserializationContext deserializationContext ) throws IOException { - Map groups = new HashMap<>(); + var groups = new HashMap(); JsonNode node = jsonParser.getCodec().readTree(jsonParser); - for (JsonNode n : node) { + for (var n : node) { GroupInfo g; if (n.hasNonNull("masterKey")) { // a v2 group - GroupIdV2 groupId = GroupIdV2.fromBase64(n.get("groupId").asText()); + var groupId = GroupIdV2.fromBase64(n.get("groupId").asText()); try { - GroupMasterKey masterKey = new GroupMasterKey(Base64.getDecoder() - .decode(n.get("masterKey").asText())); + var masterKey = new GroupMasterKey(Base64.getDecoder().decode(n.get("masterKey").asText())); g = new GroupInfoV2(groupId, masterKey); } catch (InvalidInputException | IllegalArgumentException e) { throw new AssertionError("Invalid master key for group " + groupId.toBase64()); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java index 3e728c28..6d604300 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java @@ -36,7 +36,7 @@ public class MessageCache { return Stream.of(dir); } - final File[] files = Objects.requireNonNull(dir.listFiles()); + final var files = Objects.requireNonNull(dir.listFiles()); if (files.length == 0) { try { Files.delete(dir.toPath()); @@ -50,11 +50,11 @@ public class MessageCache { } public CachedMessage cacheMessage(SignalServiceEnvelope envelope) { - final long now = new Date().getTime(); - final String source = envelope.hasSource() ? envelope.getSourceAddress().getLegacyIdentifier() : ""; + final var now = new Date().getTime(); + final var source = envelope.hasSource() ? envelope.getSourceAddress().getLegacyIdentifier() : ""; try { - File cacheFile = getMessageCacheFile(source, now, envelope.getTimestamp()); + var cacheFile = getMessageCacheFile(source, now, envelope.getTimestamp()); MessageCacheUtils.storeEnvelope(envelope, cacheFile); return new CachedMessage(cacheFile); } catch (IOException e) { @@ -72,7 +72,7 @@ public class MessageCache { } private File getMessageCacheFile(String sender, long now, long timestamp) throws IOException { - File cachePath = getMessageCachePath(sender); + var cachePath = getMessageCachePath(sender); IOUtils.createPrivateDirectories(cachePath); return new File(cachePath, now + "_" + timestamp); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/ProfileStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/ProfileStore.java index 516b57dc..dc69a7ee 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/ProfileStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/ProfileStore.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Base64; import java.util.List; -import java.util.UUID; public class ProfileStore { @@ -34,7 +33,7 @@ public class ProfileStore { private final List profiles = new ArrayList<>(); public SignalProfileEntry getProfileEntry(SignalServiceAddress serviceAddress) { - for (SignalProfileEntry entry : profiles) { + for (var entry : profiles) { if (entry.getServiceAddress().matches(serviceAddress)) { return entry; } @@ -43,7 +42,7 @@ public class ProfileStore { } public ProfileKey getProfileKey(SignalServiceAddress serviceAddress) { - for (SignalProfileEntry entry : profiles) { + for (var entry : profiles) { if (entry.getServiceAddress().matches(serviceAddress)) { return entry.getProfileKey(); } @@ -58,12 +57,8 @@ public class ProfileStore { SignalProfile profile, ProfileKeyCredential profileKeyCredential ) { - SignalProfileEntry newEntry = new SignalProfileEntry(serviceAddress, - profileKey, - now, - profile, - profileKeyCredential); - for (int i = 0; i < profiles.size(); i++) { + var newEntry = new SignalProfileEntry(serviceAddress, profileKey, now, profile, profileKeyCredential); + for (var i = 0; i < profiles.size(); i++) { if (profiles.get(i).getServiceAddress().matches(serviceAddress)) { profiles.set(i, newEntry); return; @@ -74,8 +69,8 @@ public class ProfileStore { } public void storeProfileKey(SignalServiceAddress serviceAddress, ProfileKey profileKey) { - SignalProfileEntry newEntry = new SignalProfileEntry(serviceAddress, profileKey, 0, null, null); - for (int i = 0; i < profiles.size(); i++) { + var newEntry = new SignalProfileEntry(serviceAddress, profileKey, 0, null, null); + for (var i = 0; i < profiles.size(); i++) { if (profiles.get(i).getServiceAddress().matches(serviceAddress)) { if (!profiles.get(i).getProfileKey().equals(profileKey)) { profiles.set(i, newEntry); @@ -95,13 +90,13 @@ public class ProfileStore { ) throws IOException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); - List addresses = new ArrayList<>(); + var addresses = new ArrayList(); if (node.isArray()) { - for (JsonNode entry : node) { - String name = entry.hasNonNull("name") ? entry.get("name").asText() : null; - UUID uuid = entry.hasNonNull("uuid") ? UuidUtil.parseOrNull(entry.get("uuid").asText()) : null; - final SignalServiceAddress serviceAddress = new SignalServiceAddress(uuid, name); + for (var entry : node) { + var name = entry.hasNonNull("name") ? entry.get("name").asText() : null; + var uuid = entry.hasNonNull("uuid") ? UuidUtil.parseOrNull(entry.get("uuid").asText()) : null; + final var serviceAddress = new SignalServiceAddress(uuid, name); ProfileKey profileKey = null; try { profileKey = new ProfileKey(Base64.getDecoder().decode(entry.get("profileKey").asText())); @@ -115,8 +110,8 @@ public class ProfileStore { } catch (Throwable ignored) { } } - long lastUpdateTimestamp = entry.get("lastUpdateTimestamp").asLong(); - SignalProfile profile = jsonProcessor.treeToValue(entry.get("profile"), SignalProfile.class); + var lastUpdateTimestamp = entry.get("lastUpdateTimestamp").asLong(); + var profile = jsonProcessor.treeToValue(entry.get("profile"), SignalProfile.class); addresses.add(new SignalProfileEntry(serviceAddress, profileKey, lastUpdateTimestamp, @@ -136,8 +131,8 @@ public class ProfileStore { List profiles, JsonGenerator json, SerializerProvider serializerProvider ) throws IOException { json.writeStartArray(); - for (SignalProfileEntry profileEntry : profiles) { - final SignalServiceAddress address = profileEntry.getServiceAddress(); + for (var profileEntry : profiles) { + final var address = profileEntry.getServiceAddress(); json.writeStartObject(); if (address.getNumber().isPresent()) { json.writeStringField("name", address.getNumber().get()); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java index 9f01b719..ed04e556 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java @@ -25,7 +25,6 @@ import java.util.ArrayList; import java.util.Base64; import java.util.Date; import java.util.List; -import java.util.UUID; public class JsonIdentityKeyStore implements IdentityKeyStore { @@ -85,7 +84,7 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { public boolean saveIdentity( SignalServiceAddress serviceAddress, IdentityKey identityKey, TrustLevel trustLevel, Date added ) { - for (IdentityInfo id : identities) { + for (var id : identities) { if (!id.address.matches(serviceAddress) || !id.identityKey.equals(identityKey)) { continue; } @@ -111,7 +110,7 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { public void setIdentityTrustLevel( SignalServiceAddress serviceAddress, IdentityKey identityKey, TrustLevel trustLevel ) { - for (IdentityInfo id : identities) { + for (var id : identities) { if (!id.address.matches(serviceAddress) || !id.identityKey.equals(identityKey)) { continue; } @@ -129,10 +128,10 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { @Override public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) { // TODO implement possibility for different handling of incoming/outgoing trust decisions - SignalServiceAddress serviceAddress = resolveSignalServiceAddress(address.getName()); - boolean trustOnFirstUse = true; + var serviceAddress = resolveSignalServiceAddress(address.getName()); + var trustOnFirstUse = true; - for (IdentityInfo id : identities) { + for (var id : identities) { if (!id.address.matches(serviceAddress)) { continue; } @@ -149,20 +148,20 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { @Override public IdentityKey getIdentity(SignalProtocolAddress address) { - SignalServiceAddress serviceAddress = resolveSignalServiceAddress(address.getName()); - IdentityInfo identity = getIdentity(serviceAddress); + var serviceAddress = resolveSignalServiceAddress(address.getName()); + var identity = getIdentity(serviceAddress); return identity == null ? null : identity.getIdentityKey(); } public IdentityInfo getIdentity(SignalServiceAddress serviceAddress) { long maxDate = 0; IdentityInfo maxIdentity = null; - for (IdentityInfo id : this.identities) { + for (var id : this.identities) { if (!id.address.matches(serviceAddress)) { continue; } - final long time = id.getDateAdded().getTime(); + final var time = id.getDateAdded().getTime(); if (maxIdentity == null || maxDate <= time) { maxDate = time; maxIdentity = id; @@ -177,8 +176,8 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { } public List getIdentities(SignalServiceAddress serviceAddress) { - List identities = new ArrayList<>(); - for (IdentityInfo identity : this.identities) { + var identities = new ArrayList(); + for (var identity : this.identities) { if (identity.address.matches(serviceAddress)) { identities.add(identity); } @@ -194,34 +193,32 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { ) throws IOException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); - int localRegistrationId = node.get("registrationId").asInt(); - IdentityKeyPair identityKeyPair = new IdentityKeyPair(Base64.getDecoder() - .decode(node.get("identityKey").asText())); + var localRegistrationId = node.get("registrationId").asInt(); + var identityKeyPair = new IdentityKeyPair(Base64.getDecoder().decode(node.get("identityKey").asText())); - JsonIdentityKeyStore keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId); + var keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId); - JsonNode trustedKeysNode = node.get("trustedKeys"); + var trustedKeysNode = node.get("trustedKeys"); if (trustedKeysNode.isArray()) { - for (JsonNode trustedKey : trustedKeysNode) { - String trustedKeyName = trustedKey.hasNonNull("name") ? trustedKey.get("name").asText() : null; + for (var trustedKey : trustedKeysNode) { + var trustedKeyName = trustedKey.hasNonNull("name") ? trustedKey.get("name").asText() : null; if (UuidUtil.isUuid(trustedKeyName)) { // Ignore identities that were incorrectly created with UUIDs as name continue; } - UUID uuid = trustedKey.hasNonNull("uuid") + var uuid = trustedKey.hasNonNull("uuid") ? UuidUtil.parseOrNull(trustedKey.get("uuid").asText()) : null; - final SignalServiceAddress serviceAddress = uuid == null + final var serviceAddress = uuid == null ? Utils.getSignalServiceAddressFromIdentifier(trustedKeyName) : new SignalServiceAddress(uuid, trustedKeyName); try { - IdentityKey id = new IdentityKey(Base64.getDecoder() - .decode(trustedKey.get("identityKey").asText()), 0); - TrustLevel trustLevel = trustedKey.hasNonNull("trustLevel") ? TrustLevel.fromInt(trustedKey.get( + var id = new IdentityKey(Base64.getDecoder().decode(trustedKey.get("identityKey").asText()), 0); + var trustLevel = trustedKey.hasNonNull("trustLevel") ? TrustLevel.fromInt(trustedKey.get( "trustLevel").asInt()) : TrustLevel.TRUSTED_UNVERIFIED; - Date added = trustedKey.hasNonNull("addedTimestamp") ? new Date(trustedKey.get("addedTimestamp") + var added = trustedKey.hasNonNull("addedTimestamp") ? new Date(trustedKey.get("addedTimestamp") .asLong()) : new Date(); keyStore.saveIdentity(serviceAddress, id, trustLevel, added); } catch (InvalidKeyException e) { @@ -251,7 +248,7 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { Base64.getEncoder() .encodeToString(jsonIdentityKeyStore.getIdentityKeyPair().getPublicKey().serialize())); json.writeArrayFieldStart("trustedKeys"); - for (IdentityInfo trustedKey : jsonIdentityKeyStore.identities) { + for (var trustedKey : jsonIdentityKeyStore.identities) { json.writeStartObject(); if (trustedKey.getAddress().getNumber().isPresent()) { json.writeStringField("name", trustedKey.getAddress().getNumber().get()); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonPreKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonPreKeyStore.java index 8529d0dd..9ff0d8ea 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonPreKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonPreKeyStore.java @@ -69,16 +69,16 @@ class JsonPreKeyStore implements PreKeyStore { ) throws IOException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); - Map preKeyMap = new HashMap<>(); + var preKeyMap = new HashMap(); if (node.isArray()) { - for (JsonNode preKey : node) { - final int preKeyId = preKey.get("id").asInt(); - final byte[] preKeyRecord = Base64.getDecoder().decode(preKey.get("record").asText()); + for (var preKey : node) { + final var preKeyId = preKey.get("id").asInt(); + final var preKeyRecord = Base64.getDecoder().decode(preKey.get("record").asText()); preKeyMap.put(preKeyId, preKeyRecord); } } - JsonPreKeyStore keyStore = new JsonPreKeyStore(); + var keyStore = new JsonPreKeyStore(); keyStore.addPreKeys(preKeyMap); return keyStore; @@ -92,7 +92,7 @@ class JsonPreKeyStore implements PreKeyStore { JsonPreKeyStore jsonPreKeyStore, JsonGenerator json, SerializerProvider serializerProvider ) throws IOException { json.writeStartArray(); - for (Map.Entry preKey : jsonPreKeyStore.store.entrySet()) { + for (var preKey : jsonPreKeyStore.store.entrySet()) { json.writeStartObject(); json.writeNumberField("id", preKey.getKey()); json.writeStringField("record", Base64.getEncoder().encodeToString(preKey.getValue())); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSessionStore.java index 81a8adb2..94d2d681 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSessionStore.java @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.Base64; import java.util.LinkedList; import java.util.List; -import java.util.UUID; class JsonSessionStore implements SignalServiceSessionStore { @@ -49,14 +48,14 @@ class JsonSessionStore implements SignalServiceSessionStore { @Override public synchronized SessionRecord loadSession(SignalProtocolAddress address) { - SignalServiceAddress serviceAddress = resolveSignalServiceAddress(address.getName()); - for (SessionInfo info : sessions) { + var serviceAddress = resolveSignalServiceAddress(address.getName()); + for (var info : sessions) { if (info.address.matches(serviceAddress) && info.deviceId == address.getDeviceId()) { try { return new SessionRecord(info.sessionRecord); } catch (IOException e) { logger.warn("Failed to load session, resetting session: {}", e.getMessage()); - final SessionRecord sessionRecord = new SessionRecord(); + final var sessionRecord = new SessionRecord(); info.sessionRecord = sessionRecord.serialize(); return sessionRecord; } @@ -72,10 +71,10 @@ class JsonSessionStore implements SignalServiceSessionStore { @Override public synchronized List getSubDeviceSessions(String name) { - SignalServiceAddress serviceAddress = resolveSignalServiceAddress(name); + var serviceAddress = resolveSignalServiceAddress(name); - List deviceIds = new LinkedList<>(); - for (SessionInfo info : sessions) { + var deviceIds = new LinkedList(); + for (var info : sessions) { if (info.address.matches(serviceAddress) && info.deviceId != 1) { deviceIds.add(info.deviceId); } @@ -86,8 +85,8 @@ class JsonSessionStore implements SignalServiceSessionStore { @Override public synchronized void storeSession(SignalProtocolAddress address, SessionRecord record) { - SignalServiceAddress serviceAddress = resolveSignalServiceAddress(address.getName()); - for (SessionInfo info : sessions) { + var serviceAddress = resolveSignalServiceAddress(address.getName()); + for (var info : sessions) { if (info.address.matches(serviceAddress) && info.deviceId == address.getDeviceId()) { if (!info.address.getUuid().isPresent() || !info.address.getNumber().isPresent()) { info.address = serviceAddress; @@ -102,8 +101,8 @@ class JsonSessionStore implements SignalServiceSessionStore { @Override public synchronized boolean containsSession(SignalProtocolAddress address) { - SignalServiceAddress serviceAddress = resolveSignalServiceAddress(address.getName()); - for (SessionInfo info : sessions) { + var serviceAddress = resolveSignalServiceAddress(address.getName()); + for (var info : sessions) { if (info.address.matches(serviceAddress) && info.deviceId == address.getDeviceId()) { return true; } @@ -113,13 +112,13 @@ class JsonSessionStore implements SignalServiceSessionStore { @Override public synchronized void deleteSession(SignalProtocolAddress address) { - SignalServiceAddress serviceAddress = resolveSignalServiceAddress(address.getName()); + var serviceAddress = resolveSignalServiceAddress(address.getName()); sessions.removeIf(info -> info.address.matches(serviceAddress) && info.deviceId == address.getDeviceId()); } @Override public synchronized void deleteAllSessions(String name) { - SignalServiceAddress serviceAddress = resolveSignalServiceAddress(name); + var serviceAddress = resolveSignalServiceAddress(name); deleteAllSessions(serviceAddress); } @@ -129,7 +128,7 @@ class JsonSessionStore implements SignalServiceSessionStore { @Override public void archiveSession(final SignalProtocolAddress address) { - final SessionRecord sessionRecord = loadSession(address); + final var sessionRecord = loadSession(address); if (sessionRecord == null) { return; } @@ -138,9 +137,9 @@ class JsonSessionStore implements SignalServiceSessionStore { } public void archiveAllSessions() { - for (SessionInfo info : sessions) { + for (var info : sessions) { try { - final SessionRecord sessionRecord = new SessionRecord(info.sessionRecord); + final var sessionRecord = new SessionRecord(info.sessionRecord); sessionRecord.archiveCurrentState(); info.sessionRecord = sessionRecord.serialize(); } catch (IOException ignored) { @@ -156,23 +155,23 @@ class JsonSessionStore implements SignalServiceSessionStore { ) throws IOException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); - JsonSessionStore sessionStore = new JsonSessionStore(); + var sessionStore = new JsonSessionStore(); if (node.isArray()) { - for (JsonNode session : node) { - String sessionName = session.hasNonNull("name") ? session.get("name").asText() : null; + for (var session : node) { + var sessionName = session.hasNonNull("name") ? session.get("name").asText() : null; if (UuidUtil.isUuid(sessionName)) { // Ignore sessions that were incorrectly created with UUIDs as name continue; } - UUID uuid = session.hasNonNull("uuid") ? UuidUtil.parseOrNull(session.get("uuid").asText()) : null; - final SignalServiceAddress serviceAddress = uuid == null + var uuid = session.hasNonNull("uuid") ? UuidUtil.parseOrNull(session.get("uuid").asText()) : null; + final var serviceAddress = uuid == null ? Utils.getSignalServiceAddressFromIdentifier(sessionName) : new SignalServiceAddress(uuid, sessionName); - final int deviceId = session.get("deviceId").asInt(); - final byte[] record = Base64.getDecoder().decode(session.get("record").asText()); - SessionInfo sessionInfo = new SessionInfo(serviceAddress, deviceId, record); + final var deviceId = session.get("deviceId").asInt(); + final var record = Base64.getDecoder().decode(session.get("record").asText()); + var sessionInfo = new SessionInfo(serviceAddress, deviceId, record); sessionStore.sessions.add(sessionInfo); } } @@ -188,7 +187,7 @@ class JsonSessionStore implements SignalServiceSessionStore { JsonSessionStore jsonSessionStore, JsonGenerator json, SerializerProvider serializerProvider ) throws IOException { json.writeStartArray(); - for (SessionInfo sessionInfo : jsonSessionStore.sessions) { + for (var sessionInfo : jsonSessionStore.sessions) { json.writeStartObject(); if (sessionInfo.address.getNumber().isPresent()) { json.writeStringField("name", sessionInfo.address.getNumber().get()); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignedPreKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignedPreKeyStore.java index a45287b4..655e372a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignedPreKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignedPreKeyStore.java @@ -51,9 +51,9 @@ class JsonSignedPreKeyStore implements SignedPreKeyStore { @Override public List loadSignedPreKeys() { try { - List results = new LinkedList<>(); + var results = new LinkedList(); - for (byte[] serialized : store.values()) { + for (var serialized : store.values()) { results.add(new SignedPreKeyRecord(serialized)); } @@ -86,16 +86,16 @@ class JsonSignedPreKeyStore implements SignedPreKeyStore { ) throws IOException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); - Map preKeyMap = new HashMap<>(); + var preKeyMap = new HashMap(); if (node.isArray()) { - for (JsonNode preKey : node) { - final int preKeyId = preKey.get("id").asInt(); - final byte[] preKeyRecord = Base64.getDecoder().decode(preKey.get("record").asText()); + for (var preKey : node) { + final var preKeyId = preKey.get("id").asInt(); + final var preKeyRecord = Base64.getDecoder().decode(preKey.get("record").asText()); preKeyMap.put(preKeyId, preKeyRecord); } } - JsonSignedPreKeyStore keyStore = new JsonSignedPreKeyStore(); + var keyStore = new JsonSignedPreKeyStore(); keyStore.addSignedPreKeys(preKeyMap); return keyStore; @@ -109,7 +109,7 @@ class JsonSignedPreKeyStore implements SignedPreKeyStore { JsonSignedPreKeyStore jsonPreKeyStore, JsonGenerator json, SerializerProvider serializerProvider ) throws IOException { json.writeStartArray(); - for (Map.Entry signedPreKey : jsonPreKeyStore.store.entrySet()) { + for (var signedPreKey : jsonPreKeyStore.store.entrySet()) { json.writeStartObject(); json.writeNumberField("id", signedPreKey.getKey()); json.writeStringField("record", Base64.getEncoder().encodeToString(signedPreKey.getValue())); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/RecipientStore.java index 60634ae5..93cca233 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/RecipientStore.java @@ -17,7 +17,6 @@ import org.whispersystems.signalservice.api.util.UuidUtil; import java.io.IOException; import java.util.HashSet; import java.util.Set; -import java.util.UUID; public class RecipientStore { @@ -33,7 +32,7 @@ public class RecipientStore { return serviceAddress; } - for (SignalServiceAddress address : addresses) { + for (var address : addresses) { if (address.matches(serviceAddress)) { return address; } @@ -54,13 +53,13 @@ public class RecipientStore { ) throws IOException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); - Set addresses = new HashSet<>(); + var addresses = new HashSet(); if (node.isArray()) { - for (JsonNode recipient : node) { - String recipientName = recipient.get("name").asText(); - UUID uuid = UuidUtil.parseOrThrow(recipient.get("uuid").asText()); - final SignalServiceAddress serviceAddress = new SignalServiceAddress(uuid, recipientName); + for (var recipient : node) { + var recipientName = recipient.get("name").asText(); + var uuid = UuidUtil.parseOrThrow(recipient.get("uuid").asText()); + final var serviceAddress = new SignalServiceAddress(uuid, recipientName); addresses.add(serviceAddress); } } @@ -76,7 +75,7 @@ public class RecipientStore { Set addresses, JsonGenerator json, SerializerProvider serializerProvider ) throws IOException { json.writeStartArray(); - for (SignalServiceAddress address : addresses) { + for (var address : addresses) { json.writeStartObject(); json.writeStringField("name", address.getNumber().get()); json.writeStringField("uuid", address.getUuid().get().toString()); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/stickers/StickerStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/stickers/StickerStore.java index 710be035..8d227575 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/stickers/StickerStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/stickers/StickerStore.java @@ -12,7 +12,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.io.IOException; import java.util.Base64; -import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -36,9 +35,9 @@ public class StickerStore { public void serialize( final Map value, final JsonGenerator jgen, final SerializerProvider provider ) throws IOException { - final Collection stickers = value.values(); + final var stickers = value.values(); jgen.writeStartArray(stickers.size()); - for (Sticker sticker : stickers) { + for (var sticker : stickers) { jgen.writeStartObject(); jgen.writeStringField("packId", Base64.getEncoder().encodeToString(sticker.getPackId())); jgen.writeStringField("packKey", Base64.getEncoder().encodeToString(sticker.getPackKey())); @@ -55,12 +54,12 @@ public class StickerStore { public Map deserialize( JsonParser jsonParser, DeserializationContext deserializationContext ) throws IOException { - Map stickers = new HashMap<>(); + var stickers = new HashMap(); JsonNode node = jsonParser.getCodec().readTree(jsonParser); - for (JsonNode n : node) { - byte[] packId = Base64.getDecoder().decode(n.get("packId").asText()); - byte[] packKey = Base64.getDecoder().decode(n.get("packKey").asText()); - boolean installed = n.get("installed").asBoolean(false); + for (var n : node) { + var packId = Base64.getDecoder().decode(n.get("packId").asText()); + var packKey = Base64.getDecoder().decode(n.get("packKey").asText()); + var installed = n.get("installed").asBoolean(false); stickers.put(packId, new Sticker(packId, packKey, installed)); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/threads/LegacyJsonThreadStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/threads/LegacyJsonThreadStore.java index f37360a2..81810713 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/threads/LegacyJsonThreadStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/threads/LegacyJsonThreadStore.java @@ -47,10 +47,10 @@ public class LegacyJsonThreadStore { public Map deserialize( JsonParser jsonParser, DeserializationContext deserializationContext ) throws IOException { - Map threads = new HashMap<>(); + var threads = new HashMap(); JsonNode node = jsonParser.getCodec().readTree(jsonParser); - for (JsonNode n : node) { - ThreadInfo t = jsonProcessor.treeToValue(n, ThreadInfo.class); + for (var n : node) { + var t = jsonProcessor.treeToValue(n, ThreadInfo.class); threads.put(t.id, t); } diff --git a/lib/src/main/java/org/asamk/signal/manager/util/AttachmentUtils.java b/lib/src/main/java/org/asamk/signal/manager/util/AttachmentUtils.java index ec043cfd..1909711d 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/AttachmentUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/AttachmentUtils.java @@ -18,7 +18,7 @@ public class AttachmentUtils { List signalServiceAttachments = null; if (attachments != null) { signalServiceAttachments = new ArrayList<>(attachments.size()); - for (String attachment : attachments) { + for (var attachment : attachments) { try { signalServiceAttachments.add(createAttachment(new File(attachment))); } catch (IOException e) { @@ -30,7 +30,7 @@ public class AttachmentUtils { } public static SignalServiceAttachmentStream createAttachment(File attachmentFile) throws IOException { - final StreamDetails streamDetails = Utils.createStreamDetailsFromFile(attachmentFile); + final var streamDetails = Utils.createStreamDetailsFromFile(attachmentFile); return createAttachment(streamDetails, Optional.of(attachmentFile.getName())); } @@ -38,7 +38,7 @@ public class AttachmentUtils { StreamDetails streamDetails, Optional name ) { // TODO mabybe add a parameter to set the voiceNote, borderless, preview, width, height and caption option - final long uploadTimestamp = System.currentTimeMillis(); + final var uploadTimestamp = System.currentTimeMillis(); Optional preview = Optional.absent(); Optional caption = Optional.absent(); Optional blurHash = Optional.absent(); diff --git a/lib/src/main/java/org/asamk/signal/manager/util/IOUtils.java b/lib/src/main/java/org/asamk/signal/manager/util/IOUtils.java index 8f47c9f4..3cc708d8 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/IOUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/IOUtils.java @@ -7,7 +7,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.util.EnumSet; @@ -20,13 +19,13 @@ import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; public class IOUtils { public static File createTempFile() throws IOException { - final File tempFile = File.createTempFile("signal-cli_tmp_", ".tmp"); + final var tempFile = File.createTempFile("signal-cli_tmp_", ".tmp"); tempFile.deleteOnExit(); return tempFile; } public static byte[] readFully(InputStream in) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); + var baos = new ByteArrayOutputStream(); IOUtils.copyStream(in, baos); return baos.toByteArray(); } @@ -36,7 +35,7 @@ public class IOUtils { return; } - final Path path = file.toPath(); + final var path = file.toPath(); try { Set perms = EnumSet.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE); Files.createDirectories(path, PosixFilePermissions.asFileAttribute(perms)); @@ -46,7 +45,7 @@ public class IOUtils { } public static void createPrivateFile(File path) throws IOException { - final Path file = path.toPath(); + final var file = path.toPath(); try { Set perms = EnumSet.of(OWNER_READ, OWNER_WRITE); Files.createFile(file, PosixFilePermissions.asFileAttribute(perms)); @@ -66,7 +65,7 @@ public class IOUtils { } public static void copyStream(InputStream input, OutputStream output, int bufferSize) throws IOException { - byte[] buffer = new byte[bufferSize]; + var buffer = new byte[bufferSize]; int read; while ((read = input.read(buffer)) != -1) { diff --git a/lib/src/main/java/org/asamk/signal/manager/util/KeyUtils.java b/lib/src/main/java/org/asamk/signal/manager/util/KeyUtils.java index b5567b57..5167331a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/KeyUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/KeyUtils.java @@ -6,8 +6,6 @@ import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.libsignal.ecc.Curve; -import org.whispersystems.libsignal.ecc.ECKeyPair; -import org.whispersystems.libsignal.ecc.ECPrivateKey; import org.whispersystems.libsignal.state.PreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.libsignal.util.Medium; @@ -26,19 +24,19 @@ public class KeyUtils { } public static IdentityKeyPair generateIdentityKeyPair() { - ECKeyPair djbKeyPair = Curve.generateKeyPair(); - IdentityKey djbIdentityKey = new IdentityKey(djbKeyPair.getPublicKey()); - ECPrivateKey djbPrivateKey = djbKeyPair.getPrivateKey(); + var djbKeyPair = Curve.generateKeyPair(); + var djbIdentityKey = new IdentityKey(djbKeyPair.getPublicKey()); + var djbPrivateKey = djbKeyPair.getPrivateKey(); return new IdentityKeyPair(djbIdentityKey, djbPrivateKey); } public static List generatePreKeyRecords(final int offset, final int batchSize) { - List records = new ArrayList<>(batchSize); - for (int i = 0; i < batchSize; i++) { - int preKeyId = (offset + i) % Medium.MAX_VALUE; - ECKeyPair keyPair = Curve.generateKeyPair(); - PreKeyRecord record = new PreKeyRecord(preKeyId, keyPair); + var records = new ArrayList(batchSize); + for (var i = 0; i < batchSize; i++) { + var preKeyId = (offset + i) % Medium.MAX_VALUE; + var keyPair = Curve.generateKeyPair(); + var record = new PreKeyRecord(preKeyId, keyPair); records.add(record); } @@ -48,7 +46,7 @@ public class KeyUtils { public static SignedPreKeyRecord generateSignedPreKeyRecord( final IdentityKeyPair identityKeyPair, final int signedPreKeyId ) { - ECKeyPair keyPair = Curve.generateKeyPair(); + var keyPair = Curve.generateKeyPair(); byte[] signature; try { signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize()); @@ -83,12 +81,12 @@ public class KeyUtils { } private static String getSecret(int size) { - byte[] secret = getSecretBytes(size); + var secret = getSecretBytes(size); return Base64.getEncoder().encodeToString(secret); } public static byte[] getSecretBytes(int size) { - byte[] secret = new byte[size]; + var secret = new byte[size]; secureRandom.nextBytes(secret); return secret; } diff --git a/lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java b/lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java index 8661c10b..05ff976e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java @@ -16,32 +16,32 @@ import java.util.UUID; public class MessageCacheUtils { public static SignalServiceEnvelope loadEnvelope(File file) throws IOException { - try (FileInputStream f = new FileInputStream(file)) { - DataInputStream in = new DataInputStream(f); - int version = in.readInt(); + try (var f = new FileInputStream(file)) { + var in = new DataInputStream(f); + var version = in.readInt(); if (version > 4) { return null; } - int type = in.readInt(); - String source = in.readUTF(); + var type = in.readInt(); + var source = in.readUTF(); UUID sourceUuid = null; if (version >= 3) { sourceUuid = UuidUtil.parseOrNull(in.readUTF()); } - int sourceDevice = in.readInt(); + var sourceDevice = in.readInt(); if (version == 1) { // read legacy relay field in.readUTF(); } - long timestamp = in.readLong(); + var timestamp = in.readLong(); byte[] content = null; - int contentLen = in.readInt(); + var contentLen = in.readInt(); if (contentLen > 0) { content = new byte[contentLen]; in.readFully(content); } byte[] legacyMessage = null; - int legacyMessageLen = in.readInt(); + var legacyMessageLen = in.readInt(); if (legacyMessageLen > 0) { legacyMessage = new byte[legacyMessageLen]; in.readFully(legacyMessage); @@ -75,8 +75,8 @@ public class MessageCacheUtils { } public static void storeEnvelope(SignalServiceEnvelope envelope, File file) throws IOException { - try (FileOutputStream f = new FileOutputStream(file)) { - try (DataOutputStream out = new DataOutputStream(f)) { + try (var f = new FileOutputStream(file)) { + try (var out = new DataOutputStream(f)) { out.writeInt(4); // version out.writeInt(envelope.getType()); out.writeUTF(envelope.getSourceE164().isPresent() ? envelope.getSourceE164().get() : ""); @@ -96,7 +96,7 @@ public class MessageCacheUtils { out.writeInt(0); } out.writeLong(envelope.getServerReceivedTimestamp()); - String uuid = envelope.getUuid(); + var uuid = envelope.getUuid(); out.writeUTF(uuid == null ? "" : uuid); out.writeLong(envelope.getServerDeliveredTimestamp()); } diff --git a/lib/src/main/java/org/asamk/signal/manager/util/PinHashing.java b/lib/src/main/java/org/asamk/signal/manager/util/PinHashing.java index 2fd2d802..5dc5a5bc 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/PinHashing.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/PinHashing.java @@ -12,18 +12,18 @@ public final class PinHashing { } public static HashedPin hashPin(String pin, KeyBackupService.HashSession hashSession) { - final Argon2Parameters params = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id).withParallelism(1) + final var params = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id).withParallelism(1) .withIterations(32) .withVersion(Argon2Parameters.ARGON2_VERSION_13) .withMemoryAsKB(16 * 1024) .withSalt(hashSession.hashSalt()) .build(); - final Argon2BytesGenerator generator = new Argon2BytesGenerator(); + final var generator = new Argon2BytesGenerator(); generator.init(params); return PinHasher.hashPin(PinHasher.normalize(pin), password -> { - byte[] output = new byte[64]; + var output = new byte[64]; generator.generateBytes(password, output); return output; }); diff --git a/lib/src/main/java/org/asamk/signal/manager/util/ProfileUtils.java b/lib/src/main/java/org/asamk/signal/manager/util/ProfileUtils.java index 11362444..63820b51 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/ProfileUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/ProfileUtils.java @@ -13,11 +13,11 @@ public class ProfileUtils { public static SignalProfile decryptProfile( final ProfileKey profileKey, final SignalServiceProfile encryptedProfile ) { - ProfileCipher profileCipher = new ProfileCipher(profileKey); + var profileCipher = new ProfileCipher(profileKey); try { - String name = decryptName(encryptedProfile.getName(), profileCipher); - String about = decryptName(encryptedProfile.getAbout(), profileCipher); - String aboutEmoji = decryptName(encryptedProfile.getAboutEmoji(), profileCipher); + var name = decryptName(encryptedProfile.getName(), profileCipher); + var about = decryptName(encryptedProfile.getAbout(), profileCipher); + var aboutEmoji = decryptName(encryptedProfile.getAboutEmoji(), profileCipher); String unidentifiedAccess; try { unidentifiedAccess = encryptedProfile.getUnidentifiedAccess() == null diff --git a/lib/src/main/java/org/asamk/signal/manager/util/StickerUtils.java b/lib/src/main/java/org/asamk/signal/manager/util/StickerUtils.java index fd5ce77b..2fa8bc97 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/StickerUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/StickerUtils.java @@ -13,8 +13,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.List; -import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class StickerUtils { @@ -33,7 +31,7 @@ public class StickerUtils { throw new StickerPackInvalidException("Could not find manifest.json"); } - JsonStickerPack pack = parseStickerPack(rootPath, zip); + var pack = parseStickerPack(rootPath, zip); if (pack.stickers == null) { throw new StickerPackInvalidException("Must set a 'stickers' field."); @@ -43,8 +41,8 @@ public class StickerUtils { throw new StickerPackInvalidException("Must include stickers."); } - List stickers = new ArrayList<>(pack.stickers.size()); - for (JsonStickerPack.JsonSticker sticker : pack.stickers) { + var stickers = new ArrayList(pack.stickers.size()); + for (var sticker : pack.stickers) { if (sticker.file == null) { throw new StickerPackInvalidException("Must set a 'file' field on each sticker."); } @@ -56,9 +54,8 @@ public class StickerUtils { throw new StickerPackInvalidException("Could not find find " + sticker.file); } - String contentType = Utils.getFileMimeType(new File(sticker.file), null); - SignalServiceStickerManifestUpload.StickerInfo stickerInfo = new SignalServiceStickerManifestUpload.StickerInfo( - data.first(), + var contentType = Utils.getFileMimeType(new File(sticker.file), null); + var stickerInfo = new SignalServiceStickerManifestUpload.StickerInfo(data.first(), data.second(), Optional.fromNullable(sticker.emoji).or(""), contentType); @@ -78,7 +75,7 @@ public class StickerUtils { throw new StickerPackInvalidException("Could not find find " + pack.cover.file); } - String contentType = Utils.getFileMimeType(new File(pack.cover.file), null); + var contentType = Utils.getFileMimeType(new File(pack.cover.file), null); cover = new SignalServiceStickerManifestUpload.StickerInfo(data.first(), data.second(), Optional.fromNullable(pack.cover.emoji).or(""), @@ -102,10 +99,10 @@ public class StickerUtils { final String rootPath, final ZipFile zip, final String subfile ) throws IOException { if (zip != null) { - final ZipEntry entry = zip.getEntry(subfile); + final var entry = zip.getEntry(subfile); return new Pair<>(zip.getInputStream(entry), entry.getSize()); } else { - final File file = new File(rootPath, subfile); + final var file = new File(rootPath, subfile); return new Pair<>(new FileInputStream(file), file.length()); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/util/Utils.java b/lib/src/main/java/org/asamk/signal/manager/util/Utils.java index fb38d01a..2963a996 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/Utils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/Utils.java @@ -3,7 +3,6 @@ package org.asamk.signal.manager.util; import com.fasterxml.jackson.databind.JsonNode; import org.whispersystems.libsignal.IdentityKey; -import org.whispersystems.libsignal.fingerprint.Fingerprint; import org.whispersystems.libsignal.fingerprint.NumericFingerprintGenerator; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.StreamDetails; @@ -21,7 +20,7 @@ import java.nio.file.Files; public class Utils { public static String getFileMimeType(File file, String defaultMimeType) throws IOException { - String mime = Files.probeContentType(file.toPath()); + var mime = Files.probeContentType(file.toPath()); if (mime == null) { try (InputStream bufferedStream = new BufferedInputStream(new FileInputStream(file))) { mime = URLConnection.guessContentTypeFromStream(bufferedStream); @@ -35,8 +34,8 @@ public class Utils { public static StreamDetails createStreamDetailsFromFile(File file) throws IOException { InputStream stream = new FileInputStream(file); - final long size = file.length(); - final String mime = getFileMimeType(file, "application/octet-stream"); + final var size = file.length(); + final var mime = getFileMimeType(file, "application/octet-stream"); return new StreamDetails(stream, mime, size); } @@ -66,7 +65,7 @@ public class Utils { theirId = theirAddress.getNumber().get().getBytes(); } - Fingerprint fingerprint = new NumericFingerprintGenerator(5200).createFor(version, + var fingerprint = new NumericFingerprintGenerator(5200).createFor(version, ownId, ownIdentityKey, theirId, @@ -83,7 +82,7 @@ public class Utils { } public static JsonNode getNotNullNode(JsonNode parent, String name) throws InvalidObjectException { - JsonNode node = parent.get(name); + var node = parent.get(name); if (node == null || node.isNull()) { throw new InvalidObjectException(String.format("Incorrect file format: expected parameter %s not found ", name)); diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index 90efc20f..5f0f1cdf 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -3,10 +3,7 @@ package org.asamk.signal; import net.sourceforge.argparse4j.ArgumentParsers; import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.ArgumentParser; -import net.sourceforge.argparse4j.inf.MutuallyExclusiveGroup; import net.sourceforge.argparse4j.inf.Namespace; -import net.sourceforge.argparse4j.inf.Subparser; -import net.sourceforge.argparse4j.inf.Subparsers; import org.asamk.Signal; import org.asamk.signal.commands.Command; @@ -33,7 +30,6 @@ import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import java.io.File; import java.io.IOException; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -44,7 +40,7 @@ public class App { private final Namespace ns; static ArgumentParser buildArgumentParser() { - ArgumentParser parser = ArgumentParsers.newFor("signal-cli") + var parser = ArgumentParsers.newFor("signal-cli") .build() .defaultHelp(true) .description("Commandline interface for Signal.") @@ -59,7 +55,7 @@ public class App { parser.addArgument("-u", "--username").help("Specify your phone number, that will be used for verification."); - MutuallyExclusiveGroup mut = parser.addMutuallyExclusiveGroup(); + var mut = parser.addMutuallyExclusiveGroup(); mut.addArgument("--dbus").help("Make request via user dbus.").action(Arguments.storeTrue()); mut.addArgument("--dbus-system").help("Make request via system dbus.").action(Arguments.storeTrue()); @@ -68,11 +64,11 @@ public class App { .type(Arguments.enumStringType(OutputType.class)) .setDefault(OutputType.PLAIN_TEXT); - Subparsers subparsers = parser.addSubparsers().title("subcommands").dest("command"); + var subparsers = parser.addSubparsers().title("subcommands").dest("command"); - final Map commands = Commands.getCommands(); - for (Map.Entry entry : commands.entrySet()) { - Subparser subparser = subparsers.addParser(entry.getKey()); + final var commands = Commands.getCommands(); + for (var entry : commands.entrySet()) { + var subparser = subparsers.addParser(entry.getKey()); entry.getValue().attachToSubparser(subparser); } @@ -84,8 +80,8 @@ public class App { } public int init() { - String commandKey = ns.getString("command"); - Command command = Commands.getCommand(commandKey); + var commandKey = ns.getString("command"); + var command = Commands.getCommand(commandKey); if (command == null) { logger.error("Command not implemented!"); return 1; @@ -97,7 +93,7 @@ public class App { return 1; } - String username = ns.getString("username"); + var username = ns.getString("username"); final boolean useDbus = ns.getBoolean("dbus"); final boolean useDbusSystem = ns.getBoolean("dbus_system"); @@ -107,14 +103,14 @@ public class App { } final File dataPath; - String config = ns.getString("config"); + var config = ns.getString("config"); if (config != null) { dataPath = new File(config); } else { dataPath = getDefaultDataPath(); } - final ServiceEnvironment serviceEnvironment = ServiceEnvironment.LIVE; + final var serviceEnvironment = ServiceEnvironment.LIVE; if (!ServiceConfig.getCapabilities().isGv2()) { logger.warn("WARNING: Support for new group V2 is disabled," @@ -136,7 +132,7 @@ public class App { } if (username == null) { - List usernames = Manager.getAllLocalUsernames(dataPath); + var usernames = Manager.getAllLocalUsernames(dataPath); if (usernames.size() == 0) { System.err.println("No local users found, you first need to register or link an account"); return 1; @@ -172,7 +168,7 @@ public class App { private int handleProvisioningCommand( final ProvisioningCommand command, final File dataPath, final ServiceEnvironment serviceEnvironment ) { - ProvisioningManager pm = ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT); + var pm = ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT); return command.handleCommand(ns, pm); } @@ -189,7 +185,7 @@ public class App { logger.error("Error loading or creating state file: {}", e.getMessage()); return 2; } - try (RegistrationManager m = manager) { + try (var m = manager) { return command.handleCommand(ns, m); } catch (IOException e) { logger.error("Cleanup failed", e); @@ -203,7 +199,7 @@ public class App { final File dataPath, final ServiceEnvironment serviceEnvironment ) { - try (Manager m = loadManager(username, dataPath, serviceEnvironment)) { + try (var m = loadManager(username, dataPath, serviceEnvironment)) { if (m == null) { return 2; } @@ -221,14 +217,14 @@ public class App { final ServiceEnvironment serviceEnvironment, final List usernames ) { - final List managers = usernames.stream() + final var managers = usernames.stream() .map(u -> loadManager(u, dataPath, serviceEnvironment)) .filter(Objects::nonNull) .collect(Collectors.toList()); - int result = command.handleCommand(ns, managers); + var result = command.handleCommand(ns, managers); - for (Manager m : managers) { + for (var m : managers) { try { m.close(); } catch (IOException e) { @@ -270,8 +266,8 @@ public class App { } else { busType = DBusConnection.DBusBusType.SESSION; } - try (DBusConnection dBusConn = DBusConnection.getConnection(busType)) { - Signal ts = dBusConn.getRemoteObject(DbusConfig.getBusname(), + try (var dBusConn = DBusConnection.getConnection(busType)) { + var ts = dBusConn.getRemoteObject(DbusConfig.getBusname(), DbusConfig.getObjectPath(username), Signal.class); @@ -302,14 +298,14 @@ public class App { * @return the data directory to be used by signal-cli. */ private static File getDefaultDataPath() { - File dataPath = new File(IOUtils.getDataHomeDir(), "signal-cli"); + var dataPath = new File(IOUtils.getDataHomeDir(), "signal-cli"); if (dataPath.exists()) { return dataPath; } - File configPath = new File(System.getProperty("user.home"), ".config"); + var configPath = new File(System.getProperty("user.home"), ".config"); - File legacySettingsPath = new File(configPath, "signal"); + var legacySettingsPath = new File(configPath, "signal"); if (legacySettingsPath.exists()) { return legacySettingsPath; } diff --git a/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java b/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java index 0cffd7b1..e0bd793d 100644 --- a/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java @@ -5,15 +5,10 @@ import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupUtils; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.exceptions.DBusException; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; import org.whispersystems.signalservice.api.messages.SignalServiceGroup; -import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; -import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage; -import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; -import org.whispersystems.signalservice.api.push.SignalServiceAddress; import java.util.ArrayList; import java.util.List; @@ -46,11 +41,11 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler { e.printStackTrace(); } } else if (content != null) { - final SignalServiceAddress sender = !envelope.isUnidentifiedSender() && envelope.hasSource() + final var sender = !envelope.isUnidentifiedSender() && envelope.hasSource() ? envelope.getSourceAddress() : content.getSender(); if (content.getReceiptMessage().isPresent()) { - final SignalServiceReceiptMessage receiptMessage = content.getReceiptMessage().get(); + final var receiptMessage = content.getReceiptMessage().get(); if (receiptMessage.isDeliveryReceipt()) { for (long timestamp : receiptMessage.getTimestamps()) { try { @@ -63,9 +58,9 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler { } } } else if (content.getDataMessage().isPresent()) { - SignalServiceDataMessage message = content.getDataMessage().get(); + var message = content.getDataMessage().get(); - byte[] groupId = getGroupId(message); + var groupId = getGroupId(message); if (!message.isEndSession() && ( groupId == null || message.getGroupContext().get().getGroupV1Type() == null @@ -83,15 +78,15 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler { } } } else if (content.getSyncMessage().isPresent()) { - SignalServiceSyncMessage sync_message = content.getSyncMessage().get(); + var sync_message = content.getSyncMessage().get(); if (sync_message.getSent().isPresent()) { - SentTranscriptMessage transcript = sync_message.getSent().get(); + var transcript = sync_message.getSent().get(); if (transcript.getDestination().isPresent() || transcript.getMessage() .getGroupContext() .isPresent()) { - SignalServiceDataMessage message = transcript.getMessage(); - byte[] groupId = getGroupId(message); + var message = transcript.getMessage(); + var groupId = getGroupId(message); try { conn.sendMessage(new Signal.SyncMessageReceived(objectPath, @@ -118,9 +113,9 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler { } static private List getAttachments(SignalServiceDataMessage message, Manager m) { - List attachments = new ArrayList<>(); + var attachments = new ArrayList(); if (message.getAttachments().isPresent()) { - for (SignalServiceAttachment attachment : message.getAttachments().get()) { + for (var attachment : message.getAttachments().get()) { if (attachment.isPointer()) { attachments.add(m.getAttachmentFile(attachment.asPointer().getRemoteId()).getAbsolutePath()); } diff --git a/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java b/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java index 818f2881..38657f5e 100644 --- a/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java @@ -10,7 +10,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; import java.io.IOException; import java.util.HashMap; -import java.util.Map; public class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler { @@ -26,7 +25,7 @@ public class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler @Override public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) { - final Map object = new HashMap<>(); + final var object = new HashMap(); if (exception != null) { object.put("error", new JsonError(exception)); } diff --git a/src/main/java/org/asamk/signal/Main.java b/src/main/java/org/asamk/signal/Main.java index 2ec1470c..88ae06ca 100644 --- a/src/main/java/org/asamk/signal/Main.java +++ b/src/main/java/org/asamk/signal/Main.java @@ -18,7 +18,6 @@ package org.asamk.signal; import net.sourceforge.argparse4j.ArgumentParsers; import net.sourceforge.argparse4j.impl.Arguments; -import net.sourceforge.argparse4j.inf.ArgumentParser; import net.sourceforge.argparse4j.inf.ArgumentParserException; import net.sourceforge.argparse4j.inf.Namespace; @@ -36,11 +35,11 @@ public class Main { // Configuring the logger needs to happen before any logger is initialized configureLogging(isVerbose(args)); - ArgumentParser parser = App.buildArgumentParser(); + var parser = App.buildArgumentParser(); - Namespace ns = parser.parseArgsOrFail(args); + var ns = parser.parseArgsOrFail(args); - int res = new App(ns).init(); + var res = new App(ns).init(); System.exit(res); } @@ -51,7 +50,7 @@ public class Main { } private static boolean isVerbose(String[] args) { - ArgumentParser parser = ArgumentParsers.newFor("signal-cli").build().defaultHelp(false); + var parser = ArgumentParsers.newFor("signal-cli").build().defaultHelp(false); parser.addArgument("--verbose").action(Arguments.storeTrue()); Namespace ns; diff --git a/src/main/java/org/asamk/signal/PlainTextWriterImpl.java b/src/main/java/org/asamk/signal/PlainTextWriterImpl.java index 19874d55..d6536481 100644 --- a/src/main/java/org/asamk/signal/PlainTextWriterImpl.java +++ b/src/main/java/org/asamk/signal/PlainTextWriterImpl.java @@ -20,7 +20,7 @@ public final class PlainTextWriterImpl implements PlainTextWriter { @Override public void println(String format, Object... args) throws IOException { - final String message = MessageFormatter.arrayFormat(format, args).getMessage(); + final var message = MessageFormatter.arrayFormat(format, args).getMessage(); writer.write(message); writer.write(System.lineSeparator()); diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java index 6e9e1a94..8c75fcba 100644 --- a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java @@ -3,46 +3,24 @@ package org.asamk.signal; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupUtils; -import org.asamk.signal.manager.storage.groups.GroupInfo; import org.asamk.signal.util.DateUtils; import org.asamk.signal.util.Util; import org.slf4j.helpers.MessageFormatter; import org.whispersystems.libsignal.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup; import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; import org.whispersystems.signalservice.api.messages.SignalServiceTypingMessage; -import org.whispersystems.signalservice.api.messages.calls.AnswerMessage; -import org.whispersystems.signalservice.api.messages.calls.BusyMessage; -import org.whispersystems.signalservice.api.messages.calls.HangupMessage; -import org.whispersystems.signalservice.api.messages.calls.IceUpdateMessage; -import org.whispersystems.signalservice.api.messages.calls.OfferMessage; -import org.whispersystems.signalservice.api.messages.calls.OpaqueMessage; import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage; -import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage; -import org.whispersystems.signalservice.api.messages.multidevice.ConfigurationMessage; -import org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage; -import org.whispersystems.signalservice.api.messages.multidevice.KeysMessage; -import org.whispersystems.signalservice.api.messages.multidevice.MessageRequestResponseMessage; -import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage; -import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage; import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; -import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage; -import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage; -import org.whispersystems.signalservice.api.messages.multidevice.ViewOnceOpenMessage; import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.SignalServiceAddress; -import java.io.File; import java.io.IOException; import java.util.Base64; -import java.util.List; import java.util.stream.Collectors; public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { @@ -68,7 +46,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { PlainTextWriter writer = new PlainTextWriterImpl(System.out); if (envelope.hasSource()) { - SignalServiceAddress source = envelope.getSourceAddress(); + var source = envelope.getSourceAddress(); writer.println("Envelope from: {} (device: {})", formatContact(source), envelope.getSourceDevice()); if (source.getRelay().isPresent()) { writer.println("Relayed by: {}", source.getRelay().get()); @@ -86,7 +64,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } else if (envelope.isSignalMessage() || envelope.isPreKeySignalMessage() || envelope.isUnidentifiedSender()) { if (exception != null) { if (exception instanceof UntrustedIdentityException) { - UntrustedIdentityException e = (UntrustedIdentityException) exception; + var e = (UntrustedIdentityException) exception; writer.println( "The user’s key is untrusted, either the user has reinstalled Signal or a third party sent this message."); writer.println( @@ -112,28 +90,28 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { DateUtils.formatTimestamp(content.getServerDeliveredTimestamp())); if (content.getDataMessage().isPresent()) { - SignalServiceDataMessage message = content.getDataMessage().get(); + var message = content.getDataMessage().get(); printDataMessage(writer, message); } if (content.getSyncMessage().isPresent()) { writer.println("Received a sync message"); - SignalServiceSyncMessage syncMessage = content.getSyncMessage().get(); + var syncMessage = content.getSyncMessage().get(); printSyncMessage(writer, syncMessage); } if (content.getCallMessage().isPresent()) { writer.println("Received a call message"); - SignalServiceCallMessage callMessage = content.getCallMessage().get(); + var callMessage = content.getCallMessage().get(); printCallMessage(writer.indentedWriter(), callMessage); } if (content.getReceiptMessage().isPresent()) { writer.println("Received a receipt message"); - SignalServiceReceiptMessage receiptMessage = content.getReceiptMessage().get(); + var receiptMessage = content.getReceiptMessage().get(); printReceiptMessage(writer.indentedWriter(), receiptMessage); } if (content.getTypingMessage().isPresent()) { writer.println("Received a typing message"); - SignalServiceTypingMessage typingMessage = content.getTypingMessage().get(); + var typingMessage = content.getTypingMessage().get(); printTypingMessage(writer.indentedWriter(), typingMessage); } } @@ -156,32 +134,32 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } if (message.getGroupContext().isPresent()) { writer.println("Group info:"); - final SignalServiceGroupContext groupContext = message.getGroupContext().get(); + final var groupContext = message.getGroupContext().get(); printGroupContext(writer.indentedWriter(), groupContext); } if (message.getGroupCallUpdate().isPresent()) { writer.println("Group call update:"); - final SignalServiceDataMessage.GroupCallUpdate groupCallUpdate = message.getGroupCallUpdate().get(); + final var groupCallUpdate = message.getGroupCallUpdate().get(); writer.indentedWriter().println("Era id: {}", groupCallUpdate.getEraId()); } if (message.getPreviews().isPresent()) { writer.println("Previews:"); - final List previews = message.getPreviews().get(); - for (SignalServiceDataMessage.Preview preview : previews) { + final var previews = message.getPreviews().get(); + for (var preview : previews) { writer.println("- Preview"); printPreview(writer.indentedWriter(), preview); } } if (message.getSharedContacts().isPresent()) { - final List sharedContacts = message.getSharedContacts().get(); + final var sharedContacts = message.getSharedContacts().get(); writer.println("Contacts:"); - for (SharedContact contact : sharedContacts) { + for (var contact : sharedContacts) { writer.println("- Contact:"); printSharedContact(writer.indentedWriter(), contact); } } if (message.getSticker().isPresent()) { - final SignalServiceDataMessage.Sticker sticker = message.getSticker().get(); + final var sticker = message.getSticker().get(); writer.println("Sticker:"); printSticker(writer.indentedWriter(), sticker); } @@ -199,27 +177,27 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } if (message.getReaction().isPresent()) { writer.println("Reaction:"); - final SignalServiceDataMessage.Reaction reaction = message.getReaction().get(); + final var reaction = message.getReaction().get(); printReaction(writer.indentedWriter(), reaction); } if (message.getQuote().isPresent()) { writer.println("Quote:"); - SignalServiceDataMessage.Quote quote = message.getQuote().get(); + var quote = message.getQuote().get(); printQuote(writer.indentedWriter(), quote); } if (message.getRemoteDelete().isPresent()) { - final SignalServiceDataMessage.RemoteDelete remoteDelete = message.getRemoteDelete().get(); + final var remoteDelete = message.getRemoteDelete().get(); writer.println("Remote delete message: timestamp = {}", remoteDelete.getTargetSentTimestamp()); } if (message.getMentions().isPresent()) { writer.println("Mentions:"); - for (SignalServiceDataMessage.Mention mention : message.getMentions().get()) { + for (var mention : message.getMentions().get()) { printMention(writer, mention); } } if (message.getAttachments().isPresent()) { writer.println("Attachments:"); - for (SignalServiceAttachment attachment : message.getAttachments().get()) { + for (var attachment : message.getAttachments().get()) { writer.println("- Attachment:"); printAttachment(writer.indentedWriter(), attachment); } @@ -233,7 +211,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { writer.println("Timestamp: {}", DateUtils.formatTimestamp(typingMessage.getTimestamp())); if (typingMessage.getGroupId().isPresent()) { writer.println("Group Info:"); - final GroupId groupId = GroupId.unknownVersion(typingMessage.getGroupId().get()); + final var groupId = GroupId.unknownVersion(typingMessage.getGroupId().get()); printGroupInfo(writer.indentedWriter(), groupId); } } @@ -261,34 +239,34 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { final PlainTextWriter writer, final SignalServiceCallMessage callMessage ) throws IOException { if (callMessage.getDestinationDeviceId().isPresent()) { - final Integer deviceId = callMessage.getDestinationDeviceId().get(); + final var deviceId = callMessage.getDestinationDeviceId().get(); writer.println("Destination device id: {}", deviceId); } if (callMessage.getAnswerMessage().isPresent()) { - AnswerMessage answerMessage = callMessage.getAnswerMessage().get(); + var answerMessage = callMessage.getAnswerMessage().get(); writer.println("Answer message: {}, sdp: {})", answerMessage.getId(), answerMessage.getSdp()); } if (callMessage.getBusyMessage().isPresent()) { - BusyMessage busyMessage = callMessage.getBusyMessage().get(); + var busyMessage = callMessage.getBusyMessage().get(); writer.println("Busy message: {}", busyMessage.getId()); } if (callMessage.getHangupMessage().isPresent()) { - HangupMessage hangupMessage = callMessage.getHangupMessage().get(); + var hangupMessage = callMessage.getHangupMessage().get(); writer.println("Hangup message: {}", hangupMessage.getId()); } if (callMessage.getIceUpdateMessages().isPresent()) { writer.println("Ice update messages:"); - List iceUpdateMessages = callMessage.getIceUpdateMessages().get(); - for (IceUpdateMessage iceUpdateMessage : iceUpdateMessages) { + var iceUpdateMessages = callMessage.getIceUpdateMessages().get(); + for (var iceUpdateMessage : iceUpdateMessages) { writer.println("- {}, sdp: {}", iceUpdateMessage.getId(), iceUpdateMessage.getSdp()); } } if (callMessage.getOfferMessage().isPresent()) { - OfferMessage offerMessage = callMessage.getOfferMessage().get(); + var offerMessage = callMessage.getOfferMessage().get(); writer.println("Offer message: {}, sdp: {}", offerMessage.getId(), offerMessage.getSdp()); } if (callMessage.getOpaqueMessage().isPresent()) { - final OpaqueMessage opaqueMessage = callMessage.getOpaqueMessage().get(); + final var opaqueMessage = callMessage.getOpaqueMessage().get(); writer.println("Opaque message: size {}", opaqueMessage.getOpaque().length); } } @@ -297,8 +275,8 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { final PlainTextWriter writer, final SignalServiceSyncMessage syncMessage ) throws IOException { if (syncMessage.getContacts().isPresent()) { - final ContactsMessage contactsMessage = syncMessage.getContacts().get(); - String type = contactsMessage.isComplete() ? "complete" : "partial"; + final var contactsMessage = syncMessage.getContacts().get(); + var type = contactsMessage.isComplete() ? "complete" : "partial"; writer.println("Received {} sync contacts:", type); printAttachment(writer.indentedWriter(), contactsMessage.getContactsStream()); } @@ -308,7 +286,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } if (syncMessage.getRead().isPresent()) { writer.println("Received sync read messages list"); - for (ReadMessage rm : syncMessage.getRead().get()) { + for (var rm : syncMessage.getRead().get()) { writer.println("- From: {} Message timestamp: {}", formatContact(rm.getSender()), DateUtils.formatTimestamp(rm.getTimestamp())); @@ -333,7 +311,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } if (syncMessage.getSent().isPresent()) { writer.println("Received sync sent message"); - final SentTranscriptMessage sentTranscriptMessage = syncMessage.getSent().get(); + final var sentTranscriptMessage = syncMessage.getSent().get(); String to; if (sentTranscriptMessage.getDestination().isPresent()) { to = formatContact(sentTranscriptMessage.getDestination().get()); @@ -353,28 +331,28 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { .println("Expiration started at: {}", DateUtils.formatTimestamp(sentTranscriptMessage.getExpirationStartTimestamp())); } - SignalServiceDataMessage message = sentTranscriptMessage.getMessage(); + var message = sentTranscriptMessage.getMessage(); printDataMessage(writer.indentedWriter(), message); } if (syncMessage.getBlockedList().isPresent()) { writer.println("Received sync message with block list"); writer.println("Blocked numbers:"); - final BlockedListMessage blockedList = syncMessage.getBlockedList().get(); - for (SignalServiceAddress address : blockedList.getAddresses()) { + final var blockedList = syncMessage.getBlockedList().get(); + for (var address : blockedList.getAddresses()) { writer.println("- {}", address.getLegacyIdentifier()); } } if (syncMessage.getVerified().isPresent()) { writer.println("Received sync message with verified identities:"); - final VerifiedMessage verifiedMessage = syncMessage.getVerified().get(); + final var verifiedMessage = syncMessage.getVerified().get(); writer.println("- {}: {}", formatContact(verifiedMessage.getDestination()), verifiedMessage.getVerified()); - String safetyNumber = Util.formatSafetyNumber(m.computeSafetyNumber(verifiedMessage.getDestination(), + var safetyNumber = Util.formatSafetyNumber(m.computeSafetyNumber(verifiedMessage.getDestination(), verifiedMessage.getIdentityKey())); writer.indentedWriter().println(safetyNumber); } if (syncMessage.getConfiguration().isPresent()) { writer.println("Received sync message with configuration:"); - final ConfigurationMessage configurationMessage = syncMessage.getConfiguration().get(); + final var configurationMessage = syncMessage.getConfiguration().get(); if (configurationMessage.getReadReceipts().isPresent()) { writer.println("- Read receipts: {}", configurationMessage.getReadReceipts().get() ? "enabled" : "disabled"); @@ -393,21 +371,20 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } } if (syncMessage.getFetchType().isPresent()) { - final SignalServiceSyncMessage.FetchType fetchType = syncMessage.getFetchType().get(); + final var fetchType = syncMessage.getFetchType().get(); writer.println("Received sync message with fetch type: {}", fetchType); } if (syncMessage.getViewOnceOpen().isPresent()) { - final ViewOnceOpenMessage viewOnceOpenMessage = syncMessage.getViewOnceOpen().get(); + final var viewOnceOpenMessage = syncMessage.getViewOnceOpen().get(); writer.println("Received sync message with view once open message:"); writer.indentedWriter().println("Sender: {}", formatContact(viewOnceOpenMessage.getSender())); writer.indentedWriter() .println("Timestamp: {}", DateUtils.formatTimestamp(viewOnceOpenMessage.getTimestamp())); } if (syncMessage.getStickerPackOperations().isPresent()) { - final List stickerPackOperationMessages = syncMessage.getStickerPackOperations() - .get(); + final var stickerPackOperationMessages = syncMessage.getStickerPackOperations().get(); writer.println("Received sync message with sticker pack operations:"); - for (StickerPackOperationMessage m : stickerPackOperationMessages) { + for (var m : stickerPackOperationMessages) { writer.println("- {}", m.getType().isPresent() ? m.getType().get() : ""); if (m.getPackId().isPresent()) { writer.indentedWriter() @@ -420,7 +397,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } } if (syncMessage.getMessageRequestResponse().isPresent()) { - final MessageRequestResponseMessage requestResponseMessage = syncMessage.getMessageRequestResponse().get(); + final var requestResponseMessage = syncMessage.getMessageRequestResponse().get(); writer.println("Received message request response:"); writer.indentedWriter().println("Type: {}", requestResponseMessage.getType()); if (requestResponseMessage.getGroupId().isPresent()) { @@ -434,7 +411,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } } if (syncMessage.getKeys().isPresent()) { - final KeysMessage keysMessage = syncMessage.getKeys().get(); + final var keysMessage = syncMessage.getKeys().get(); writer.println("Received sync message with keys:"); if (keysMessage.getStorageService().isPresent()) { writer.println("- storage key: length: {}", keysMessage.getStorageService().get().serialize().length); @@ -482,13 +459,13 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { writer.println("Text: {}", quote.getText()); if (quote.getMentions() != null && quote.getMentions().size() > 0) { writer.println("Mentions:"); - for (SignalServiceDataMessage.Mention mention : quote.getMentions()) { + for (var mention : quote.getMentions()) { printMention(writer, mention); } } if (quote.getAttachments().size() > 0) { writer.println("Attachments:"); - for (SignalServiceDataMessage.Quote.QuotedAttachment attachment : quote.getAttachments()) { + for (var attachment : quote.getAttachments()) { writer.println("- Filename: {}", attachment.getFileName()); writer.indent(w -> { w.println("Type: {}", attachment.getContentType()); @@ -503,7 +480,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { private void printSharedContact(final PlainTextWriter writer, final SharedContact contact) throws IOException { writer.println("Name:"); - SharedContact.Name name = contact.getName(); + var name = contact.getName(); writer.indent(w -> { if (name.getDisplay().isPresent() && !name.getDisplay().get().isBlank()) { w.println("Display name: {}", name.getDisplay().get()); @@ -526,7 +503,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { }); if (contact.getAvatar().isPresent()) { - SharedContact.Avatar avatar = contact.getAvatar().get(); + var avatar = contact.getAvatar().get(); writer.println("Avatar: (profile: {})", avatar.isProfile()); printAttachment(writer.indentedWriter(), avatar.getAttachment()); } @@ -537,7 +514,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { if (contact.getPhone().isPresent()) { writer.println("Phone details:"); - for (SharedContact.Phone phone : contact.getPhone().get()) { + for (var phone : contact.getPhone().get()) { writer.println("- Phone:"); writer.indent(w -> { if (phone.getValue() != null) { @@ -555,7 +532,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { if (contact.getEmail().isPresent()) { writer.println("Email details:"); - for (SharedContact.Email email : contact.getEmail().get()) { + for (var email : contact.getEmail().get()) { writer.println("- Email:"); writer.indent(w -> { if (email.getValue() != null) { @@ -573,7 +550,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { if (contact.getAddress().isPresent()) { writer.println("Address details:"); - for (SharedContact.PostalAddress address : contact.getAddress().get()) { + for (var address : contact.getAddress().get()) { writer.println("- Address:"); writer.indent(w -> { if (address.getType() != null) { @@ -611,14 +588,14 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { private void printGroupContext( final PlainTextWriter writer, final SignalServiceGroupContext groupContext ) throws IOException { - final GroupId groupId = GroupUtils.getGroupId(groupContext); + final var groupId = GroupUtils.getGroupId(groupContext); if (groupContext.getGroupV1().isPresent()) { - SignalServiceGroup groupInfo = groupContext.getGroupV1().get(); + var groupInfo = groupContext.getGroupV1().get(); printGroupInfo(writer, groupId); writer.println("Type: {}", groupInfo.getType()); if (groupInfo.getMembers().isPresent()) { writer.println("Members:"); - for (SignalServiceAddress member : groupInfo.getMembers().get()) { + for (var member : groupInfo.getMembers().get()) { writer.println("- {}", formatContact(member)); } } @@ -627,7 +604,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { printAttachment(writer.indentedWriter(), groupInfo.getAvatar().get()); } } else if (groupContext.getGroupV2().isPresent()) { - final SignalServiceGroupV2 groupInfo = groupContext.getGroupV2().get(); + final var groupInfo = groupContext.getGroupV2().get(); printGroupInfo(writer, groupId); writer.println("Revision: {}", groupInfo.getRevision()); writer.println("Master key length: {}", groupInfo.getMasterKey().serialize().length); @@ -638,7 +615,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { private void printGroupInfo(final PlainTextWriter writer, final GroupId groupId) throws IOException { writer.println("Id: {}", groupId.toBase64()); - GroupInfo group = m.getGroup(groupId); + var group = m.getGroup(groupId); if (group != null) { writer.println("Name: {}", group.getTitle()); } else { @@ -649,8 +626,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { private void printMention( PlainTextWriter writer, SignalServiceDataMessage.Mention mention ) throws IOException { - final SignalServiceAddress address = m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), - null)); + final var address = m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), null)); writer.println("- {}: {} (length: {})", formatContact(address), mention.getStart(), mention.getLength()); } @@ -658,7 +634,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { writer.println("Content-Type: {}", attachment.getContentType()); writer.println("Type: {}", attachment.isPointer() ? "Pointer" : attachment.isStream() ? "Stream" : ""); if (attachment.isPointer()) { - final SignalServiceAttachmentPointer pointer = attachment.asPointer(); + final var pointer = attachment.asPointer(); writer.println("Id: {} Key length: {}", pointer.getRemoteId(), pointer.getKey().length); if (pointer.getUploadTimestamp() > 0) { writer.println("Upload timestamp: {}", DateUtils.formatTimestamp(pointer.getUploadTimestamp())); @@ -679,7 +655,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { if (pointer.getWidth() > 0 || pointer.getHeight() > 0) { writer.println("Dimensions: {}x{}", pointer.getWidth(), pointer.getHeight()); } - File file = m.getAttachmentFile(pointer.getRemoteId()); + var file = m.getAttachmentFile(pointer.getRemoteId()); if (file.exists()) { writer.println("Stored plaintext in: {}", file); } @@ -687,8 +663,8 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { } private String formatContact(SignalServiceAddress address) { - final String number = address.getLegacyIdentifier(); - String name = m.getContactOrProfileName(number); + final var number = address.getLegacyIdentifier(); + var name = m.getContactOrProfileName(number); if (name == null) { return number; } else { diff --git a/src/main/java/org/asamk/signal/commands/BlockCommand.java b/src/main/java/org/asamk/signal/commands/BlockCommand.java index 60009cfb..9dff25c6 100644 --- a/src/main/java/org/asamk/signal/commands/BlockCommand.java +++ b/src/main/java/org/asamk/signal/commands/BlockCommand.java @@ -4,7 +4,6 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.util.Util; @@ -21,7 +20,7 @@ public class BlockCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { - for (String contact_number : ns.getList("contact")) { + for (var contact_number : ns.getList("contact")) { try { m.setContactBlocked(contact_number, true); } catch (InvalidNumberException e) { @@ -30,9 +29,9 @@ public class BlockCommand implements LocalCommand { } if (ns.getList("group") != null) { - for (String groupIdString : ns.getList("group")) { + for (var groupIdString : ns.getList("group")) { try { - GroupId groupId = Util.decodeGroupId(groupIdString); + var groupId = Util.decodeGroupId(groupIdString); m.setGroupBlocked(groupId, true); } catch (GroupIdFormatException | GroupNotFoundException e) { System.err.println(e.getMessage()); diff --git a/src/main/java/org/asamk/signal/commands/DaemonCommand.java b/src/main/java/org/asamk/signal/commands/DaemonCommand.java index 19859d45..6ee4f316 100644 --- a/src/main/java/org/asamk/signal/commands/DaemonCommand.java +++ b/src/main/java/org/asamk/signal/commands/DaemonCommand.java @@ -45,7 +45,7 @@ public class DaemonCommand implements MultiLocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { - boolean inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); + var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed if (ns.getBoolean("json")) { @@ -61,9 +61,9 @@ public class DaemonCommand implements MultiLocalCommand { busType = DBusConnection.DBusBusType.SESSION; } - try (DBusConnection conn = DBusConnection.getConnection(busType)) { - String objectPath = DbusConfig.getObjectPath(); - Thread t = run(conn, objectPath, m, ignoreAttachments, inJson); + try (var conn = DBusConnection.getConnection(busType)) { + var objectPath = DbusConfig.getObjectPath(); + var t = run(conn, objectPath, m, ignoreAttachments, inJson); conn.requestBusName(DbusConfig.getBusname()); @@ -80,7 +80,7 @@ public class DaemonCommand implements MultiLocalCommand { @Override public int handleCommand(final Namespace ns, final List managers) { - boolean inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); + var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed if (ns.getBoolean("json")) { @@ -96,17 +96,17 @@ public class DaemonCommand implements MultiLocalCommand { busType = DBusConnection.DBusBusType.SESSION; } - try (DBusConnection conn = DBusConnection.getConnection(busType)) { - List receiveThreads = new ArrayList<>(); - for (Manager m : managers) { - String objectPath = DbusConfig.getObjectPath(m.getUsername()); - Thread thread = run(conn, objectPath, m, ignoreAttachments, inJson); + try (var conn = DBusConnection.getConnection(busType)) { + var receiveThreads = new ArrayList(); + for (var m : managers) { + var objectPath = DbusConfig.getObjectPath(m.getUsername()); + var thread = run(conn, objectPath, m, ignoreAttachments, inJson); receiveThreads.add(thread); } conn.requestBusName(DbusConfig.getBusname()); - for (Thread t : receiveThreads) { + for (var t : receiveThreads) { try { t.join(); } catch (InterruptedException ignored) { @@ -124,7 +124,7 @@ public class DaemonCommand implements MultiLocalCommand { ) throws DBusException { conn.exportObject(objectPath, new DbusSignalImpl(m)); - final Thread thread = new Thread(() -> { + final var thread = new Thread(() -> { while (true) { try { m.receiveMessages(1, diff --git a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java index 4bc209cd..8fad2554 100644 --- a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java +++ b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java @@ -12,7 +12,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -38,7 +37,7 @@ public class GetUserStatusCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { // Setup the json object mapper - boolean inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); + var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed if (ns.getBoolean("json")) { @@ -56,9 +55,9 @@ public class GetUserStatusCommand implements LocalCommand { // Output if (inJson) { - final JsonWriter jsonWriter = new JsonWriter(System.out); + final var jsonWriter = new JsonWriter(System.out); - List jsonUserStatuses = registered.entrySet() + var jsonUserStatuses = registered.entrySet() .stream() .map(entry -> new JsonUserStatus(entry.getKey(), entry.getValue())) .collect(Collectors.toList()); @@ -70,7 +69,7 @@ public class GetUserStatusCommand implements LocalCommand { return 3; } } else { - for (Map.Entry entry : registered.entrySet()) { + for (var entry : registered.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } diff --git a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java index bfe46650..2a8a9c8f 100644 --- a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java @@ -4,16 +4,12 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.freedesktop.dbus.exceptions.DBusExecutionException; -import org.whispersystems.libsignal.util.Pair; import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; -import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.internal.push.exceptions.GroupPatchNotAcceptedException; import java.io.IOException; -import java.util.List; import static org.asamk.signal.util.ErrorUtils.handleAssertionError; import static org.asamk.signal.util.ErrorUtils.handleIOException; @@ -29,7 +25,7 @@ public class JoinGroupCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { final GroupInviteLinkUrl linkUrl; - String uri = ns.getString("uri"); + var uri = ns.getString("uri"); try { linkUrl = GroupInviteLinkUrl.fromUri(uri); } catch (GroupInviteLinkUrl.InvalidGroupLinkException e) { @@ -46,8 +42,8 @@ public class JoinGroupCommand implements LocalCommand { } try { - final Pair> results = m.joinGroup(linkUrl); - GroupId newGroupId = results.first(); + final var results = m.joinGroup(linkUrl); + var newGroupId = results.first(); if (!m.getGroup(newGroupId).isMember(m.getSelfAddress())) { System.out.println("Requested to join group \"" + newGroupId.toBase64() + "\""); } else { diff --git a/src/main/java/org/asamk/signal/commands/LinkCommand.java b/src/main/java/org/asamk/signal/commands/LinkCommand.java index 7cc9daf5..5c40dba6 100644 --- a/src/main/java/org/asamk/signal/commands/LinkCommand.java +++ b/src/main/java/org/asamk/signal/commands/LinkCommand.java @@ -21,13 +21,13 @@ public class LinkCommand implements ProvisioningCommand { @Override public int handleCommand(final Namespace ns, final ProvisioningManager m) { - String deviceName = ns.getString("name"); + var deviceName = ns.getString("name"); if (deviceName == null) { deviceName = "cli"; } try { System.out.println(m.getDeviceLinkUri()); - String username = m.finishDeviceLink(deviceName); + var username = m.finishDeviceLink(deviceName); System.out.println("Associated with: " + username); } catch (TimeoutException e) { System.err.println("Link request timed out, please try again."); diff --git a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java index 1a14e8df..dcc59856 100644 --- a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java @@ -4,9 +4,6 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.storage.contacts.ContactInfo; - -import java.util.List; public class ListContactsCommand implements LocalCommand { @@ -16,8 +13,8 @@ public class ListContactsCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { - List contacts = m.getContacts(); - for (ContactInfo c : contacts) { + var contacts = m.getContacts(); + for (var c : contacts) { System.out.println(String.format("Number: %s Name: %s Blocked: %b", c.number, c.name, c.blocked)); } return 0; diff --git a/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java b/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java index a03b078f..4946cd4a 100644 --- a/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java @@ -5,10 +5,8 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.manager.Manager; import org.asamk.signal.util.DateUtils; -import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo; import java.io.IOException; -import java.util.List; public class ListDevicesCommand implements LocalCommand { @@ -19,8 +17,8 @@ public class ListDevicesCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { try { - List devices = m.getLinkedDevices(); - for (DeviceInfo d : devices) { + var devices = m.getLinkedDevices(); + for (var d : devices) { System.out.println("Device " + d.getId() + (d.getId() == m.getDeviceId() ? " (this device)" : "") diff --git a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java index e0086cae..f3418d93 100644 --- a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java @@ -7,7 +7,6 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputType; import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.asamk.signal.manager.storage.groups.GroupInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,7 +14,6 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress; import java.io.IOException; import java.util.ArrayList; -import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -32,7 +30,7 @@ public class ListGroupsCommand implements LocalCommand { private static void printGroupPlainText(Manager m, GroupInfo group, boolean detailed) { if (detailed) { - final GroupInviteLinkUrl groupInviteLink = group.getGroupInviteLink(); + final var groupInviteLink = group.getGroupInviteLink(); System.out.println(String.format( "Id: %s Name: %s Active: %s Blocked: %b Members: %s Pending members: %s Requesting members: %s Link: %s", @@ -70,11 +68,11 @@ public class ListGroupsCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { if (ns.get("output") == OutputType.JSON) { - final JsonWriter jsonWriter = new JsonWriter(System.out); + final var jsonWriter = new JsonWriter(System.out); - List jsonGroups = new ArrayList<>(); - for (GroupInfo group : m.getGroups()) { - final GroupInviteLinkUrl groupInviteLink = group.getGroupInviteLink(); + var jsonGroups = new ArrayList(); + for (var group : m.getGroups()) { + final var groupInviteLink = group.getGroupInviteLink(); jsonGroups.add(new JsonGroup(group.getGroupId().toBase64(), group.getTitle(), @@ -96,7 +94,7 @@ public class ListGroupsCommand implements LocalCommand { return 0; } else { boolean detailed = ns.getBoolean("detailed"); - for (GroupInfo group : m.getGroups()) { + for (var group : m.getGroups()) { printGroupPlainText(m, group, detailed); } } diff --git a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java index 4caeca29..cb8aa8bc 100644 --- a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java @@ -9,12 +9,10 @@ import org.asamk.signal.util.Hex; import org.asamk.signal.util.Util; import org.whispersystems.signalservice.api.util.InvalidNumberException; -import java.util.List; - public class ListIdentitiesCommand implements LocalCommand { private static void printIdentityFingerprint(Manager m, IdentityInfo theirId) { - String digits = Util.formatSafetyNumber(m.computeSafetyNumber(theirId.getAddress(), theirId.getIdentityKey())); + var digits = Util.formatSafetyNumber(m.computeSafetyNumber(theirId.getAddress(), theirId.getIdentityKey())); System.out.println(String.format("%s: %s Added: %s Fingerprint: %s Safety Number: %s", theirId.getAddress().getNumber().orNull(), theirId.getTrustLevel(), @@ -31,14 +29,14 @@ public class ListIdentitiesCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { if (ns.get("number") == null) { - for (IdentityInfo identity : m.getIdentities()) { + for (var identity : m.getIdentities()) { printIdentityFingerprint(m, identity); } } else { - String number = ns.getString("number"); + var number = ns.getString("number"); try { - List identities = m.getIdentities(number); - for (IdentityInfo id : identities) { + var identities = m.getIdentities(number); + for (var id : identities) { printIdentityFingerprint(m, id); } } catch (InvalidNumberException e) { diff --git a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java index f258ae24..338163b0 100644 --- a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java @@ -4,16 +4,12 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; import org.asamk.signal.util.Util; -import org.whispersystems.libsignal.util.Pair; -import org.whispersystems.signalservice.api.messages.SendMessageResult; import java.io.IOException; -import java.util.List; import static org.asamk.signal.util.ErrorUtils.handleAssertionError; import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException; @@ -32,8 +28,8 @@ public class QuitGroupCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { try { - final GroupId groupId = Util.decodeGroupId(ns.getString("group")); - final Pair> results = m.sendQuitGroupMessage(groupId); + final var groupId = Util.decodeGroupId(ns.getString("group")); + final var results = m.sendQuitGroupMessage(groupId); return handleTimestampAndSendMessageResults(results.first(), results.second()); } catch (IOException e) { handleIOException(e); diff --git a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java index 5d41dde0..9693d7c2 100644 --- a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java +++ b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java @@ -48,19 +48,19 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { } public int handleCommand(final Namespace ns, final Signal signal, DBusConnection dbusconnection) { - boolean inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); + var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed if (ns.getBoolean("json")) { logger.warn("\"--json\" option has been deprecated, please use the global \"--output=json\" instead."); } - final JsonWriter jsonWriter = inJson ? new JsonWriter(System.out) : null; + final var jsonWriter = inJson ? new JsonWriter(System.out) : null; try { dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> { if (jsonWriter != null) { - JsonMessageEnvelope envelope = new JsonMessageEnvelope(messageReceived); - final Map object = Map.of("envelope", envelope); + var envelope = new JsonMessageEnvelope(messageReceived); + final var object = Map.of("envelope", envelope); try { jsonWriter.write(object); } catch (IOException e) { @@ -77,7 +77,7 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { } if (messageReceived.getAttachments().size() > 0) { System.out.println("Attachments: "); - for (String attachment : messageReceived.getAttachments()) { + for (var attachment : messageReceived.getAttachments()) { System.out.println("- Stored plaintext in: " + attachment); } } @@ -87,8 +87,8 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> { if (jsonWriter != null) { - JsonMessageEnvelope envelope = new JsonMessageEnvelope(receiptReceived); - final Map object = Map.of("envelope", envelope); + var envelope = new JsonMessageEnvelope(receiptReceived); + final var object = Map.of("envelope", envelope); try { jsonWriter.write(object); } catch (IOException e) { @@ -103,8 +103,8 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> { if (jsonWriter != null) { - JsonMessageEnvelope envelope = new JsonMessageEnvelope(syncReceived); - final Map object = Map.of("envelope", envelope); + var envelope = new JsonMessageEnvelope(syncReceived); + final var object = Map.of("envelope", envelope); try { jsonWriter.write(object); } catch (IOException e) { @@ -122,7 +122,7 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { } if (syncReceived.getAttachments().size() > 0) { System.out.println("Attachments: "); - for (String attachment : syncReceived.getAttachments()) { + for (var attachment : syncReceived.getAttachments()) { System.out.println("- Stored plaintext in: " + attachment); } } @@ -144,7 +144,7 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { - boolean inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); + var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed if (ns.getBoolean("json")) { @@ -155,16 +155,14 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { if (ns.getDouble("timeout") != null) { timeout = ns.getDouble("timeout"); } - boolean returnOnTimeout = true; + var returnOnTimeout = true; if (timeout < 0) { returnOnTimeout = false; timeout = 3600; } boolean ignoreAttachments = ns.getBoolean("ignore_attachments"); try { - final Manager.ReceiveMessageHandler handler = inJson - ? new JsonReceiveMessageHandler(m) - : new ReceiveMessageHandler(m); + final var handler = inJson ? new JsonReceiveMessageHandler(m) : new ReceiveMessageHandler(m); m.receiveMessages((long) (timeout * 1000), TimeUnit.MILLISECONDS, returnOnTimeout, diff --git a/src/main/java/org/asamk/signal/commands/RegisterCommand.java b/src/main/java/org/asamk/signal/commands/RegisterCommand.java index f7736018..d656fe0e 100644 --- a/src/main/java/org/asamk/signal/commands/RegisterCommand.java +++ b/src/main/java/org/asamk/signal/commands/RegisterCommand.java @@ -23,7 +23,7 @@ public class RegisterCommand implements RegistrationCommand { @Override public int handleCommand(final Namespace ns, final RegistrationManager m) { final boolean voiceVerification = ns.getBoolean("voice"); - final String captcha = ns.getString("captcha"); + final var captcha = ns.getString("captcha"); try { m.register(voiceVerification, captcha); diff --git a/src/main/java/org/asamk/signal/commands/SendCommand.java b/src/main/java/org/asamk/signal/commands/SendCommand.java index 73d8f2ed..f1768b76 100644 --- a/src/main/java/org/asamk/signal/commands/SendCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendCommand.java @@ -1,7 +1,6 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.impl.Arguments; -import net.sourceforge.argparse4j.inf.MutuallyExclusiveGroup; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; @@ -24,7 +23,7 @@ public class SendCommand implements DbusCommand { @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("recipient").help("Specify the recipients' phone number.").nargs("*"); - final MutuallyExclusiveGroup mutuallyExclusiveGroup = subparser.addMutuallyExclusiveGroup(); + final var mutuallyExclusiveGroup = subparser.addMutuallyExclusiveGroup(); mutuallyExclusiveGroup.addArgument("-g", "--group").help("Specify the recipient group ID."); mutuallyExclusiveGroup.addArgument("--note-to-self") .help("Send the message to self without notification.") @@ -40,11 +39,11 @@ public class SendCommand implements DbusCommand { @Override public int handleCommand(final Namespace ns, final Signal signal) { final List recipients = ns.getList("recipient"); - final Boolean isEndSession = ns.getBoolean("endsession"); - final String groupIdString = ns.getString("group"); - final Boolean isNoteToSelf = ns.getBoolean("note_to_self"); + final var isEndSession = ns.getBoolean("endsession"); + final var groupIdString = ns.getString("group"); + final var isNoteToSelf = ns.getBoolean("note_to_self"); - final boolean noRecipients = recipients == null || recipients.isEmpty(); + final var noRecipients = recipients == null || recipients.isEmpty(); if ((noRecipients && isEndSession) || (noRecipients && groupIdString == null && !isNoteToSelf)) { System.err.println("No recipients given"); System.err.println("Aborting sending."); @@ -75,7 +74,7 @@ public class SendCommand implements DbusCommand { } } - String messageText = ns.getString("message"); + var messageText = ns.getString("message"); if (messageText == null) { try { messageText = IOUtils.readAll(System.in, Charset.defaultCharset()); @@ -101,7 +100,7 @@ public class SendCommand implements DbusCommand { return 1; } - long timestamp = signal.sendGroupMessage(messageText, attachments, groupId); + var timestamp = signal.sendGroupMessage(messageText, attachments, groupId); System.out.println(timestamp); return 0; } catch (AssertionError e) { @@ -115,7 +114,7 @@ public class SendCommand implements DbusCommand { if (isNoteToSelf) { try { - long timestamp = signal.sendNoteToSelfMessage(messageText, attachments); + var timestamp = signal.sendNoteToSelfMessage(messageText, attachments); System.out.println(timestamp); return 0; } catch (AssertionError e) { @@ -131,7 +130,7 @@ public class SendCommand implements DbusCommand { } try { - long timestamp = signal.sendMessage(messageText, attachments, recipients); + var timestamp = signal.sendMessage(messageText, attachments, recipients); System.out.println(timestamp); return 0; } catch (AssertionError e) { diff --git a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java index e9ddc1f0..36d04185 100644 --- a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java @@ -5,7 +5,6 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; @@ -48,9 +47,9 @@ public class SendReactionCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { final List recipients = ns.getList("recipient"); - final String groupIdString = ns.getString("group"); + final var groupIdString = ns.getString("group"); - final boolean noRecipients = recipients == null || recipients.isEmpty(); + final var noRecipients = recipients == null || recipients.isEmpty(); if (noRecipients && groupIdString == null) { System.err.println("No recipients given"); System.err.println("Aborting sending."); @@ -61,15 +60,15 @@ public class SendReactionCommand implements LocalCommand { return 1; } - final String emoji = ns.getString("emoji"); + final var emoji = ns.getString("emoji"); final boolean isRemove = ns.getBoolean("remove"); - final String targetAuthor = ns.getString("target_author"); + final var targetAuthor = ns.getString("target_author"); final long targetTimestamp = ns.getLong("target_timestamp"); try { final Pair> results; if (groupIdString != null) { - GroupId groupId = Util.decodeGroupId(groupIdString); + var groupId = Util.decodeGroupId(groupIdString); results = m.sendGroupMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, groupId); } else { results = m.sendMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, recipients); diff --git a/src/main/java/org/asamk/signal/commands/SetPinCommand.java b/src/main/java/org/asamk/signal/commands/SetPinCommand.java index dbdc83df..fff105be 100644 --- a/src/main/java/org/asamk/signal/commands/SetPinCommand.java +++ b/src/main/java/org/asamk/signal/commands/SetPinCommand.java @@ -20,7 +20,7 @@ public class SetPinCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { try { - String registrationLockPin = ns.getString("registrationLockPin"); + var registrationLockPin = ns.getString("registrationLockPin"); m.setRegistrationLockPin(Optional.of(registrationLockPin)); return 0; } catch (UnauthenticatedResponseException e) { diff --git a/src/main/java/org/asamk/signal/commands/TrustCommand.java b/src/main/java/org/asamk/signal/commands/TrustCommand.java index 58c7371f..277291eb 100644 --- a/src/main/java/org/asamk/signal/commands/TrustCommand.java +++ b/src/main/java/org/asamk/signal/commands/TrustCommand.java @@ -1,7 +1,6 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.impl.Arguments; -import net.sourceforge.argparse4j.inf.MutuallyExclusiveGroup; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; @@ -17,7 +16,7 @@ public class TrustCommand implements LocalCommand { @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("number").help("Specify the phone number, for which to set the trust.").required(true); - MutuallyExclusiveGroup mutTrust = subparser.addMutuallyExclusiveGroup(); + var mutTrust = subparser.addMutuallyExclusiveGroup(); mutTrust.addArgument("-a", "--trust-all-known-keys") .help("Trust all known keys of this user, only use this for testing.") .action(Arguments.storeTrue()); @@ -27,15 +26,15 @@ public class TrustCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { - String number = ns.getString("number"); + var number = ns.getString("number"); if (ns.getBoolean("trust_all_known_keys")) { - boolean res = m.trustIdentityAllKeys(number); + var res = m.trustIdentityAllKeys(number); if (!res) { System.err.println("Failed to set the trust for this number, make sure the number is correct."); return 1; } } else { - String safetyNumber = ns.getString("verified_safety_number"); + var safetyNumber = ns.getString("verified_safety_number"); if (safetyNumber != null) { safetyNumber = safetyNumber.replaceAll(" ", ""); if (safetyNumber.length() == 66) { diff --git a/src/main/java/org/asamk/signal/commands/UnblockCommand.java b/src/main/java/org/asamk/signal/commands/UnblockCommand.java index d191ef22..b9d6e849 100644 --- a/src/main/java/org/asamk/signal/commands/UnblockCommand.java +++ b/src/main/java/org/asamk/signal/commands/UnblockCommand.java @@ -4,7 +4,6 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.util.Util; @@ -21,7 +20,7 @@ public class UnblockCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { - for (String contact_number : ns.getList("contact")) { + for (var contact_number : ns.getList("contact")) { try { m.setContactBlocked(contact_number, false); } catch (InvalidNumberException e) { @@ -30,9 +29,9 @@ public class UnblockCommand implements LocalCommand { } if (ns.getList("group") != null) { - for (String groupIdString : ns.getList("group")) { + for (var groupIdString : ns.getList("group")) { try { - GroupId groupId = Util.decodeGroupId(groupIdString); + var groupId = Util.decodeGroupId(groupIdString); m.setGroupBlocked(groupId, false); } catch (GroupIdFormatException | GroupNotFoundException e) { System.err.println(e.getMessage()); diff --git a/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java b/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java index c4da94a2..c2b994d6 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java @@ -23,13 +23,13 @@ public class UpdateContactCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { - String number = ns.getString("number"); - String name = ns.getString("name"); + var number = ns.getString("number"); + var name = ns.getString("name"); try { m.setContactName(number, name); - Integer expiration = ns.getInt("expiration"); + var expiration = ns.getInt("expiration"); if (expiration != null) { m.setExpirationTimer(number, expiration); } diff --git a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java index 736190b3..332bbe5e 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java @@ -40,7 +40,7 @@ public class UpdateGroupCommand implements DbusCommand { groupId = new byte[0]; } - String groupName = ns.getString("name"); + var groupName = ns.getString("name"); if (groupName == null) { groupName = ""; } @@ -50,13 +50,13 @@ public class UpdateGroupCommand implements DbusCommand { groupMembers = new ArrayList<>(); } - String groupAvatar = ns.getString("avatar"); + var groupAvatar = ns.getString("avatar"); if (groupAvatar == null) { groupAvatar = ""; } try { - byte[] newGroupId = signal.updateGroup(groupId, groupName, groupMembers, groupAvatar); + var newGroupId = signal.updateGroup(groupId, groupName, groupMembers, groupAvatar); if (groupId.length != newGroupId.length) { System.out.println("Creating new group \"" + Base64.getEncoder().encodeToString(newGroupId) + "\" …"); } diff --git a/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java b/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java index 5455f523..b8c7b08c 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java @@ -1,7 +1,6 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.impl.Arguments; -import net.sourceforge.argparse4j.inf.MutuallyExclusiveGroup; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; @@ -19,7 +18,7 @@ public class UpdateProfileCommand implements LocalCommand { subparser.addArgument("--about").help("New profile about text"); subparser.addArgument("--about-emoji").help("New profile about emoji"); - final MutuallyExclusiveGroup avatarOptions = subparser.addMutuallyExclusiveGroup(); + final var avatarOptions = subparser.addMutuallyExclusiveGroup(); avatarOptions.addArgument("--avatar").help("Path to new profile avatar"); avatarOptions.addArgument("--remove-avatar").action(Arguments.storeTrue()); @@ -28,10 +27,10 @@ public class UpdateProfileCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { - String name = ns.getString("name"); - String about = ns.getString("about"); - String aboutEmoji = ns.getString("about_emoji"); - String avatarPath = ns.getString("avatar"); + var name = ns.getString("name"); + var about = ns.getString("about"); + var aboutEmoji = ns.getString("about_emoji"); + var avatarPath = ns.getString("avatar"); boolean removeAvatar = ns.getBoolean("remove_avatar"); try { diff --git a/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java b/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java index 725f91b3..94ba9e9c 100644 --- a/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java +++ b/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java @@ -20,8 +20,8 @@ public class UploadStickerPackCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { try { - File path = new File(ns.getString("path")); - String url = m.uploadStickerPack(path); + var path = new File(ns.getString("path")); + var url = m.uploadStickerPack(path); System.out.println(url); return 0; } catch (IOException e) { diff --git a/src/main/java/org/asamk/signal/commands/VerifyCommand.java b/src/main/java/org/asamk/signal/commands/VerifyCommand.java index 7fa10b6a..a244581d 100644 --- a/src/main/java/org/asamk/signal/commands/VerifyCommand.java +++ b/src/main/java/org/asamk/signal/commands/VerifyCommand.java @@ -21,8 +21,8 @@ public class VerifyCommand implements RegistrationCommand { @Override public int handleCommand(final Namespace ns, final RegistrationManager m) { try { - String verificationCode = ns.getString("verificationCode"); - String pin = ns.getString("pin"); + var verificationCode = ns.getString("verificationCode"); + var pin = ns.getString("pin"); m.verifyAccount(verificationCode, pin); return 0; } catch (LockedException e) { diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 4af7156d..8cbbbc03 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -6,10 +6,8 @@ import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; -import org.asamk.signal.manager.storage.groups.GroupInfo; import org.asamk.signal.util.ErrorUtils; import org.freedesktop.dbus.exceptions.DBusExecutionException; -import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.push.SignalServiceAddress; @@ -41,19 +39,19 @@ public class DbusSignalImpl implements Signal { @Override public long sendMessage(final String message, final List attachments, final String recipient) { - List recipients = new ArrayList<>(1); + var recipients = new ArrayList(1); recipients.add(recipient); return sendMessage(message, attachments, recipients); } private static void checkSendMessageResult(long timestamp, SendMessageResult result) throws DBusExecutionException { - String error = ErrorUtils.getErrorMessageFromSendMessageResult(result); + var error = ErrorUtils.getErrorMessageFromSendMessageResult(result); if (error == null) { return; } - final String message = timestamp + "\nFailed to send message:\n" + error + '\n'; + final var message = timestamp + "\nFailed to send message:\n" + error + '\n'; if (result.getIdentityFailure() != null) { throw new Error.UntrustedIdentity(message); @@ -70,15 +68,15 @@ public class DbusSignalImpl implements Signal { return; } - List errors = ErrorUtils.getErrorMessagesFromSendMessageResults(results); + var errors = ErrorUtils.getErrorMessagesFromSendMessageResults(results); if (errors.size() == 0) { return; } - StringBuilder message = new StringBuilder(); + var message = new StringBuilder(); message.append(timestamp).append('\n'); message.append("Failed to send (some) messages:\n"); - for (String error : errors) { + for (var error : errors) { message.append(error).append('\n'); } @@ -88,7 +86,7 @@ public class DbusSignalImpl implements Signal { @Override public long sendMessage(final String message, final List attachments, final List recipients) { try { - final Pair> results = m.sendMessage(message, attachments, recipients); + final var results = m.sendMessage(message, attachments, recipients); checkSendMessageResults(results.first(), results.second()); return results.first(); } catch (InvalidNumberException e) { @@ -105,7 +103,7 @@ public class DbusSignalImpl implements Signal { final String message, final List attachments ) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { try { - final Pair results = m.sendSelfMessage(message, attachments); + final var results = m.sendSelfMessage(message, attachments); checkSendMessageResult(results.first(), results.second()); return results.first(); } catch (AttachmentInvalidException e) { @@ -118,7 +116,7 @@ public class DbusSignalImpl implements Signal { @Override public void sendEndSessionMessage(final List recipients) { try { - final Pair> results = m.sendEndSessionMessage(recipients); + final var results = m.sendEndSessionMessage(recipients); checkSendMessageResults(results.first(), results.second()); } catch (IOException e) { throw new Error.Failure(e.getMessage()); @@ -130,9 +128,7 @@ public class DbusSignalImpl implements Signal { @Override public long sendGroupMessage(final String message, final List attachments, final byte[] groupId) { try { - Pair> results = m.sendGroupMessage(message, - attachments, - GroupId.unknownVersion(groupId)); + var results = m.sendGroupMessage(message, attachments, GroupId.unknownVersion(groupId)); checkSendMessageResults(results.first(), results.second()); return results.first(); } catch (IOException e) { @@ -182,9 +178,9 @@ public class DbusSignalImpl implements Signal { @Override public List getGroupIds() { - List groups = m.getGroups(); - List ids = new ArrayList<>(groups.size()); - for (GroupInfo group : groups) { + var groups = m.getGroups(); + var ids = new ArrayList(groups.size()); + for (var group : groups) { ids.add(group.getGroupId().serialize()); } return ids; @@ -192,7 +188,7 @@ public class DbusSignalImpl implements Signal { @Override public String getGroupName(final byte[] groupId) { - GroupInfo group = m.getGroup(GroupId.unknownVersion(groupId)); + var group = m.getGroup(GroupId.unknownVersion(groupId)); if (group == null) { return ""; } else { @@ -202,7 +198,7 @@ public class DbusSignalImpl implements Signal { @Override public List getGroupMembers(final byte[] groupId) { - GroupInfo group = m.getGroup(GroupId.unknownVersion(groupId)); + var group = m.getGroup(GroupId.unknownVersion(groupId)); if (group == null) { return List.of(); } else { @@ -229,9 +225,10 @@ public class DbusSignalImpl implements Signal { if (avatar.isEmpty()) { avatar = null; } - final Pair> results = m.updateGroup(groupId == null - ? null - : GroupId.unknownVersion(groupId), name, members, avatar == null ? null : new File(avatar)); + final var results = m.updateGroup(groupId == null ? null : GroupId.unknownVersion(groupId), + name, + members, + avatar == null ? null : new File(avatar)); checkSendMessageResults(0, results.second()); return results.first().serialize(); } catch (IOException e) { diff --git a/src/main/java/org/asamk/signal/json/JsonAttachment.java b/src/main/java/org/asamk/signal/json/JsonAttachment.java index 1b2a7bc7..a96fc534 100644 --- a/src/main/java/org/asamk/signal/json/JsonAttachment.java +++ b/src/main/java/org/asamk/signal/json/JsonAttachment.java @@ -3,8 +3,6 @@ package org.asamk.signal.json; import com.fasterxml.jackson.annotation.JsonProperty; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream; class JsonAttachment { @@ -24,12 +22,12 @@ class JsonAttachment { this.contentType = attachment.getContentType(); if (attachment.isPointer()) { - final SignalServiceAttachmentPointer pointer = attachment.asPointer(); + final var pointer = attachment.asPointer(); this.id = pointer.getRemoteId().toString(); this.filename = pointer.getFileName().orNull(); this.size = pointer.getSize().transform(Integer::longValue).orNull(); } else { - final SignalServiceAttachmentStream stream = attachment.asStream(); + final var stream = attachment.asStream(); this.id = null; this.filename = stream.getFileName().orNull(); this.size = stream.getLength(); diff --git a/src/main/java/org/asamk/signal/json/JsonDataMessage.java b/src/main/java/org/asamk/signal/json/JsonDataMessage.java index 57facc99..6dbda978 100644 --- a/src/main/java/org/asamk/signal/json/JsonDataMessage.java +++ b/src/main/java/org/asamk/signal/json/JsonDataMessage.java @@ -6,9 +6,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.asamk.Signal; import org.asamk.signal.manager.Manager; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import java.util.List; import java.util.stream.Collectors; @@ -63,12 +60,12 @@ class JsonDataMessage { JsonDataMessage(SignalServiceDataMessage dataMessage, Manager m) { this.timestamp = dataMessage.getTimestamp(); if (dataMessage.getGroupContext().isPresent()) { - final SignalServiceGroupContext groupContext = dataMessage.getGroupContext().get(); + final var groupContext = dataMessage.getGroupContext().get(); if (groupContext.getGroupV1().isPresent()) { - SignalServiceGroup groupInfo = groupContext.getGroupV1().get(); + var groupInfo = groupContext.getGroupV1().get(); this.groupInfo = new JsonGroupInfo(groupInfo); } else if (groupContext.getGroupV2().isPresent()) { - SignalServiceGroupV2 groupInfo = groupContext.getGroupV2().get(); + var groupInfo = groupContext.getGroupV2().get(); this.groupInfo = new JsonGroupInfo(groupInfo); } else { this.groupInfo = null; diff --git a/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java b/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java index 4944a74d..8506d493 100644 --- a/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java +++ b/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java @@ -7,7 +7,6 @@ import org.asamk.Signal; import org.asamk.signal.manager.Manager; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; -import org.whispersystems.signalservice.api.push.SignalServiceAddress; import java.util.List; @@ -48,7 +47,7 @@ public class JsonMessageEnvelope { public JsonMessageEnvelope(SignalServiceEnvelope envelope, SignalServiceContent content, Manager m) { if (!envelope.isUnidentifiedSender() && envelope.hasSource()) { - SignalServiceAddress source = envelope.getSourceAddress(); + var source = envelope.getSourceAddress(); this.source = source.getLegacyIdentifier(); this.sourceDevice = envelope.getSourceDevice(); this.relay = source.getRelay().orNull(); diff --git a/src/main/java/org/asamk/signal/json/JsonSyncMessage.java b/src/main/java/org/asamk/signal/json/JsonSyncMessage.java index 11ecbbc8..7ba277d5 100644 --- a/src/main/java/org/asamk/signal/json/JsonSyncMessage.java +++ b/src/main/java/org/asamk/signal/json/JsonSyncMessage.java @@ -45,7 +45,7 @@ class JsonSyncMessage { ? new JsonSyncDataMessage(syncMessage.getSent().get(), m) : null; if (syncMessage.getBlockedList().isPresent()) { - final Base64.Encoder base64 = Base64.getEncoder(); + final var base64 = Base64.getEncoder(); this.blockedNumbers = syncMessage.getBlockedList() .get() .getAddresses() diff --git a/src/main/java/org/asamk/signal/json/JsonTypingMessage.java b/src/main/java/org/asamk/signal/json/JsonTypingMessage.java index 18548ce3..7e3b1a44 100644 --- a/src/main/java/org/asamk/signal/json/JsonTypingMessage.java +++ b/src/main/java/org/asamk/signal/json/JsonTypingMessage.java @@ -22,7 +22,7 @@ class JsonTypingMessage { JsonTypingMessage(SignalServiceTypingMessage typingMessage) { this.action = typingMessage.getAction().name(); this.timestamp = typingMessage.getTimestamp(); - final Base64.Encoder encoder = Base64.getEncoder(); + final var encoder = Base64.getEncoder(); this.groupId = typingMessage.getGroupId().transform(encoder::encodeToString).orNull(); } } diff --git a/src/main/java/org/asamk/signal/util/DateUtils.java b/src/main/java/org/asamk/signal/util/DateUtils.java index f94261bf..7f2974ae 100644 --- a/src/main/java/org/asamk/signal/util/DateUtils.java +++ b/src/main/java/org/asamk/signal/util/DateUtils.java @@ -13,7 +13,7 @@ public class DateUtils { } public static String formatTimestamp(long timestamp) { - Date date = new Date(timestamp); + var date = new Date(timestamp); final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"); // Quoted "Z" to indicate UTC, no timezone offset df.setTimeZone(tzUTC); return timestamp + " (" + df.format(date) + ")"; diff --git a/src/main/java/org/asamk/signal/util/ErrorUtils.java b/src/main/java/org/asamk/signal/util/ErrorUtils.java index f7115ea9..65e41cc8 100644 --- a/src/main/java/org/asamk/signal/util/ErrorUtils.java +++ b/src/main/java/org/asamk/signal/util/ErrorUtils.java @@ -26,14 +26,14 @@ public class ErrorUtils { if (timestamp != 0) { System.out.println(timestamp); } - List errors = getErrorMessagesFromSendMessageResults(results); + var errors = getErrorMessagesFromSendMessageResults(results); return handleSendMessageResultErrors(errors); } public static List getErrorMessagesFromSendMessageResults(List results) { - List errors = new ArrayList<>(); - for (SendMessageResult result : results) { - String error = getErrorMessageFromSendMessageResult(result); + var errors = new ArrayList(); + for (var result : results) { + var error = getErrorMessageFromSendMessageResult(result); if (error != null) { errors.add(error); } @@ -58,7 +58,7 @@ public class ErrorUtils { return 0; } System.err.println("Failed to send (some) messages:"); - for (String error : errors) { + for (var error : errors) { System.err.println(error); } return 3; diff --git a/src/main/java/org/asamk/signal/util/Hex.java b/src/main/java/org/asamk/signal/util/Hex.java index 46609ceb..f5f7a6ad 100644 --- a/src/main/java/org/asamk/signal/util/Hex.java +++ b/src/main/java/org/asamk/signal/util/Hex.java @@ -8,8 +8,8 @@ public class Hex { } public static String toString(byte[] bytes) { - StringBuffer buf = new StringBuffer(); - for (final byte aByte : bytes) { + var buf = new StringBuffer(); + for (final var aByte : bytes) { appendHexChar(buf, aByte); buf.append(" "); } @@ -17,8 +17,8 @@ public class Hex { } public static String toStringCondensed(byte[] bytes) { - StringBuffer buf = new StringBuffer(); - for (final byte aByte : bytes) { + var buf = new StringBuffer(); + for (final var aByte : bytes) { appendHexChar(buf, aByte); } return buf.toString(); @@ -30,9 +30,9 @@ public class Hex { } public static byte[] toByteArray(String s) { - int len = s.length(); - byte[] data = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { + var len = s.length(); + var data = new byte[len / 2]; + for (var i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); } return data; diff --git a/src/main/java/org/asamk/signal/util/IOUtils.java b/src/main/java/org/asamk/signal/util/IOUtils.java index 766d1905..5505e518 100644 --- a/src/main/java/org/asamk/signal/util/IOUtils.java +++ b/src/main/java/org/asamk/signal/util/IOUtils.java @@ -12,8 +12,8 @@ public class IOUtils { } public static String readAll(InputStream in, Charset charset) throws IOException { - StringWriter output = new StringWriter(); - byte[] buffer = new byte[4096]; + var output = new StringWriter(); + var buffer = new byte[4096]; int n; while (-1 != (n = in.read(buffer))) { output.write(new String(buffer, 0, n, charset)); @@ -22,7 +22,7 @@ public class IOUtils { } public static File getDataHomeDir() { - String dataHome = System.getenv("XDG_DATA_HOME"); + var dataHome = System.getenv("XDG_DATA_HOME"); if (dataHome != null) { return new File(dataHome); } diff --git a/src/main/java/org/asamk/signal/util/RandomUtils.java b/src/main/java/org/asamk/signal/util/RandomUtils.java index 19c3f18c..6af4ec12 100644 --- a/src/main/java/org/asamk/signal/util/RandomUtils.java +++ b/src/main/java/org/asamk/signal/util/RandomUtils.java @@ -6,7 +6,7 @@ import java.security.SecureRandom; public class RandomUtils { private static final ThreadLocal LOCAL_RANDOM = ThreadLocal.withInitial(() -> { - SecureRandom rand = getSecureRandomUnseeded(); + var rand = getSecureRandomUnseeded(); // Let the SecureRandom seed it self initially rand.nextBoolean(); diff --git a/src/main/java/org/asamk/signal/util/Util.java b/src/main/java/org/asamk/signal/util/Util.java index e798d537..4de49ec6 100644 --- a/src/main/java/org/asamk/signal/util/Util.java +++ b/src/main/java/org/asamk/signal/util/Util.java @@ -10,7 +10,7 @@ public class Util { } public static String getStringIfNotBlank(Optional value) { - String string = value.orNull(); + var string = value.orNull(); if (string == null || string.isBlank()) { return null; } @@ -18,10 +18,10 @@ public class Util { } public static String formatSafetyNumber(String digits) { - final int partCount = 12; - int partSize = digits.length() / partCount; - StringBuilder f = new StringBuilder(digits.length() + partCount); - for (int i = 0; i < partCount; i++) { + final var partCount = 12; + var partSize = digits.length() / partCount; + var f = new StringBuilder(digits.length() + partCount); + for (var i = 0; i < partCount; i++) { f.append(digits, i * partSize, (i * partSize) + partSize).append(" "); } return f.toString(); -- 2.51.0 From c6395b9f35a4229d297aef063597bc96919a7f36 Mon Sep 17 00:00:00 2001 From: AsamK Date: Mon, 22 Feb 2021 19:16:51 +0100 Subject: [PATCH 06/16] Use PlainTextWriter for all cli stdout output --- .../signal/commands/GetUserStatusCommand.java | 12 +- .../signal/commands/JoinGroupCommand.java | 13 +- .../asamk/signal/commands/LinkCommand.java | 11 +- .../signal/commands/ListContactsCommand.java | 14 ++- .../signal/commands/ListDevicesCommand.java | 15 +-- .../signal/commands/ListGroupsCommand.java | 26 ++-- .../commands/ListIdentitiesCommand.java | 32 +++-- .../signal/commands/QuitGroupCommand.java | 5 +- .../asamk/signal/commands/ReceiveCommand.java | 115 ++++++++++-------- .../asamk/signal/commands/SendCommand.java | 36 ++++-- .../signal/commands/SendReactionCommand.java | 5 +- .../signal/commands/UpdateGroupCommand.java | 14 ++- .../commands/UploadStickerPackCommand.java | 8 +- .../org/asamk/signal/util/ErrorUtils.java | 9 +- 14 files changed, 218 insertions(+), 97 deletions(-) diff --git a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java index 8fad2554..07de8321 100644 --- a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java +++ b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java @@ -6,6 +6,7 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputType; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,8 +70,15 @@ public class GetUserStatusCommand implements LocalCommand { return 3; } } else { - for (var entry : registered.entrySet()) { - System.out.println(entry.getKey() + ": " + entry.getValue()); + final var writer = new PlainTextWriterImpl(System.out); + + try { + for (var entry : registered.entrySet()) { + writer.println("{}: {}", entry.getKey(), entry.getValue()); + } + } catch (IOException e) { + e.printStackTrace(); + return 3; } } diff --git a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java index 2a8a9c8f..7f1cb0b0 100644 --- a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java @@ -3,9 +3,12 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.freedesktop.dbus.exceptions.DBusExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; import org.whispersystems.signalservice.internal.push.exceptions.GroupPatchNotAcceptedException; @@ -17,6 +20,8 @@ import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResu public class JoinGroupCommand implements LocalCommand { + private final static Logger logger = LoggerFactory.getLogger(JoinGroupCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("--uri").required(true).help("Specify the uri with the group invitation link."); @@ -42,14 +47,16 @@ public class JoinGroupCommand implements LocalCommand { } try { + final var writer = new PlainTextWriterImpl(System.out); + final var results = m.joinGroup(linkUrl); var newGroupId = results.first(); if (!m.getGroup(newGroupId).isMember(m.getSelfAddress())) { - System.out.println("Requested to join group \"" + newGroupId.toBase64() + "\""); + writer.println("Requested to join group \"{}\"", newGroupId.toBase64()); } else { - System.out.println("Joined group \"" + newGroupId.toBase64() + "\""); + writer.println("Joined group \"{}\"", newGroupId.toBase64()); } - return handleTimestampAndSendMessageResults(0, results.second()); + return handleTimestampAndSendMessageResults(writer, 0, results.second()); } catch (AssertionError e) { handleAssertionError(e); return 1; diff --git a/src/main/java/org/asamk/signal/commands/LinkCommand.java b/src/main/java/org/asamk/signal/commands/LinkCommand.java index 5c40dba6..fe580916 100644 --- a/src/main/java/org/asamk/signal/commands/LinkCommand.java +++ b/src/main/java/org/asamk/signal/commands/LinkCommand.java @@ -3,8 +3,11 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.ProvisioningManager; import org.asamk.signal.manager.UserAlreadyExists; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.InvalidKeyException; import java.io.IOException; @@ -14,6 +17,8 @@ import static org.asamk.signal.util.ErrorUtils.handleAssertionError; public class LinkCommand implements ProvisioningCommand { + private final static Logger logger = LoggerFactory.getLogger(LinkCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("-n", "--name").help("Specify a name to describe this new device."); @@ -21,14 +26,16 @@ public class LinkCommand implements ProvisioningCommand { @Override public int handleCommand(final Namespace ns, final ProvisioningManager m) { + final var writer = new PlainTextWriterImpl(System.out); + var deviceName = ns.getString("name"); if (deviceName == null) { deviceName = "cli"; } try { - System.out.println(m.getDeviceLinkUri()); + writer.println("{}", m.getDeviceLinkUri()); var username = m.finishDeviceLink(deviceName); - System.out.println("Associated with: " + username); + writer.println("Associated with: {}", username); } catch (TimeoutException e) { System.err.println("Link request timed out, please try again."); return 3; diff --git a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java index dcc59856..6609ec60 100644 --- a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java @@ -3,8 +3,11 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; +import java.io.IOException; + public class ListContactsCommand implements LocalCommand { @Override @@ -13,9 +16,16 @@ public class ListContactsCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { + final var writer = new PlainTextWriterImpl(System.out); + var contacts = m.getContacts(); - for (var c : contacts) { - System.out.println(String.format("Number: %s Name: %s Blocked: %b", c.number, c.name, c.blocked)); + try { + for (var c : contacts) { + writer.println("Number: {} Name: {} Blocked: {}", c.number, c.name, c.blocked); + } + } catch (IOException e) { + e.printStackTrace(); + return 3; } return 0; } diff --git a/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java b/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java index 4946cd4a..f2037239 100644 --- a/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java @@ -3,6 +3,7 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; import org.asamk.signal.util.DateUtils; @@ -16,16 +17,16 @@ public class ListDevicesCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { + final var writer = new PlainTextWriterImpl(System.out); try { var devices = m.getLinkedDevices(); for (var d : devices) { - System.out.println("Device " - + d.getId() - + (d.getId() == m.getDeviceId() ? " (this device)" : "") - + ":"); - System.out.println(" Name: " + d.getName()); - System.out.println(" Created: " + DateUtils.formatTimestamp(d.getCreated())); - System.out.println(" Last seen: " + DateUtils.formatTimestamp(d.getLastSeen())); + writer.println("- Device {}{}:", d.getId(), (d.getId() == m.getDeviceId() ? " (this device)" : "")); + writer.indent(w -> { + w.println("Name: {}", d.getName()); + w.println("Created: {}", DateUtils.formatTimestamp(d.getCreated())); + w.println("Last seen: {}", DateUtils.formatTimestamp(d.getLastSeen())); + }); } return 0; } catch (IOException e) { diff --git a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java index f3418d93..477d56a1 100644 --- a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java @@ -6,6 +6,8 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputType; +import org.asamk.signal.PlainTextWriter; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.storage.groups.GroupInfo; import org.slf4j.Logger; @@ -28,12 +30,14 @@ public class ListGroupsCommand implements LocalCommand { .collect(Collectors.toSet()); } - private static void printGroupPlainText(Manager m, GroupInfo group, boolean detailed) { + private static void printGroupPlainText( + PlainTextWriter writer, Manager m, GroupInfo group, boolean detailed + ) throws IOException { if (detailed) { final var groupInviteLink = group.getGroupInviteLink(); - System.out.println(String.format( - "Id: %s Name: %s Active: %s Blocked: %b Members: %s Pending members: %s Requesting members: %s Link: %s", + writer.println( + "Id: {} Name: {} Active: {} Blocked: {} Members: {} Pending members: {} Requesting members: {} Link: {}", group.getGroupId().toBase64(), group.getTitle(), group.isMember(m.getSelfAddress()), @@ -41,13 +45,13 @@ public class ListGroupsCommand implements LocalCommand { resolveMembers(m, group.getMembers()), resolveMembers(m, group.getPendingMembers()), resolveMembers(m, group.getRequestingMembers()), - groupInviteLink == null ? '-' : groupInviteLink.getUrl())); + groupInviteLink == null ? '-' : groupInviteLink.getUrl()); } else { - System.out.println(String.format("Id: %s Name: %s Active: %s Blocked: %b", + writer.println("Id: {} Name: {} Active: {} Blocked: {}", group.getGroupId().toBase64(), group.getTitle(), group.isMember(m.getSelfAddress()), - group.isBlocked())); + group.isBlocked()); } } @@ -93,9 +97,15 @@ public class ListGroupsCommand implements LocalCommand { return 0; } else { + final var writer = new PlainTextWriterImpl(System.out); boolean detailed = ns.getBoolean("detailed"); - for (var group : m.getGroups()) { - printGroupPlainText(m, group, detailed); + try { + for (var group : m.getGroups()) { + printGroupPlainText(writer, m, group, detailed); + } + } catch (IOException e) { + e.printStackTrace(); + return 3; } } diff --git a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java index cb8aa8bc..1f1b6258 100644 --- a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java @@ -3,22 +3,34 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.PlainTextWriter; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.storage.protocol.IdentityInfo; import org.asamk.signal.util.Hex; import org.asamk.signal.util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.util.InvalidNumberException; +import java.io.IOException; + public class ListIdentitiesCommand implements LocalCommand { - private static void printIdentityFingerprint(Manager m, IdentityInfo theirId) { + private final static Logger logger = LoggerFactory.getLogger(ListIdentitiesCommand.class); + + private static void printIdentityFingerprint(PlainTextWriter writer, Manager m, IdentityInfo theirId) { var digits = Util.formatSafetyNumber(m.computeSafetyNumber(theirId.getAddress(), theirId.getIdentityKey())); - System.out.println(String.format("%s: %s Added: %s Fingerprint: %s Safety Number: %s", - theirId.getAddress().getNumber().orNull(), - theirId.getTrustLevel(), - theirId.getDateAdded(), - Hex.toString(theirId.getFingerprint()), - digits)); + try { + writer.println("{}: {} Added: {} Fingerprint: {} Safety Number: {}", + theirId.getAddress().getNumber().orNull(), + theirId.getTrustLevel(), + theirId.getDateAdded(), + Hex.toString(theirId.getFingerprint()), + digits); + } catch (IOException e) { + e.printStackTrace(); + } } @Override @@ -28,16 +40,18 @@ public class ListIdentitiesCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { + final var writer = new PlainTextWriterImpl(System.out); + if (ns.get("number") == null) { for (var identity : m.getIdentities()) { - printIdentityFingerprint(m, identity); + printIdentityFingerprint(writer, m, identity); } } else { var number = ns.getString("number"); try { var identities = m.getIdentities(number); for (var id : identities) { - printIdentityFingerprint(m, id); + printIdentityFingerprint(writer, m, id); } } catch (InvalidNumberException e) { System.err.println("Invalid number: " + e.getMessage()); diff --git a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java index 338163b0..cdbccf19 100644 --- a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java @@ -3,6 +3,7 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; @@ -28,9 +29,11 @@ public class QuitGroupCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { try { + final var writer = new PlainTextWriterImpl(System.out); + final var groupId = Util.decodeGroupId(ns.getString("group")); final var results = m.sendQuitGroupMessage(groupId); - return handleTimestampAndSendMessageResults(results.first(), results.second()); + return handleTimestampAndSendMessageResults(writer, results.first(), results.second()); } catch (IOException e) { handleIOException(e); return 3; diff --git a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java index 9693d7c2..834bc5eb 100644 --- a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java +++ b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java @@ -8,6 +8,7 @@ import org.asamk.Signal; import org.asamk.signal.JsonReceiveMessageHandler; import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputType; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.ReceiveMessageHandler; import org.asamk.signal.json.JsonMessageEnvelope; import org.asamk.signal.manager.Manager; @@ -55,10 +56,11 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { logger.warn("\"--json\" option has been deprecated, please use the global \"--output=json\" instead."); } - final var jsonWriter = inJson ? new JsonWriter(System.out) : null; try { - dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> { - if (jsonWriter != null) { + if (inJson) { + final var jsonWriter = new JsonWriter(System.out); + + dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> { var envelope = new JsonMessageEnvelope(messageReceived); final var object = Map.of("envelope", envelope); try { @@ -66,27 +68,9 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { } catch (IOException e) { logger.error("Failed to write json object: {}", e.getMessage()); } - } else { - System.out.print(String.format("Envelope from: %s\nTimestamp: %s\nBody: %s\n", - messageReceived.getSender(), - DateUtils.formatTimestamp(messageReceived.getTimestamp()), - messageReceived.getMessage())); - if (messageReceived.getGroupId().length > 0) { - System.out.println("Group info:"); - System.out.println(" Id: " + Base64.getEncoder().encodeToString(messageReceived.getGroupId())); - } - if (messageReceived.getAttachments().size() > 0) { - System.out.println("Attachments: "); - for (var attachment : messageReceived.getAttachments()) { - System.out.println("- Stored plaintext in: " + attachment); - } - } - System.out.println(); - } - }); + }); - dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> { - if (jsonWriter != null) { + dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> { var envelope = new JsonMessageEnvelope(receiptReceived); final var object = Map.of("envelope", envelope); try { @@ -94,15 +78,9 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { } catch (IOException e) { logger.error("Failed to write json object: {}", e.getMessage()); } - } else { - System.out.print(String.format("Receipt from: %s\nTimestamp: %s\n", - receiptReceived.getSender(), - DateUtils.formatTimestamp(receiptReceived.getTimestamp()))); - } - }); - - dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> { - if (jsonWriter != null) { + }); + + dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> { var envelope = new JsonMessageEnvelope(syncReceived); final var object = Map.of("envelope", envelope); try { @@ -110,25 +88,66 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { } catch (IOException e) { logger.error("Failed to write json object: {}", e.getMessage()); } - } else { - System.out.print(String.format("Sync Envelope from: %s to: %s\nTimestamp: %s\nBody: %s\n", - syncReceived.getSource(), - syncReceived.getDestination(), - DateUtils.formatTimestamp(syncReceived.getTimestamp()), - syncReceived.getMessage())); - if (syncReceived.getGroupId().length > 0) { - System.out.println("Group info:"); - System.out.println(" Id: " + Base64.getEncoder().encodeToString(syncReceived.getGroupId())); + }); + } else { + final var writer = new PlainTextWriterImpl(System.out); + + dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> { + try { + writer.println("Envelope from: {}", messageReceived.getSender()); + writer.println("Timestamp: {}", DateUtils.formatTimestamp(messageReceived.getTimestamp())); + writer.println("Body: {}", messageReceived.getMessage()); + if (messageReceived.getGroupId().length > 0) { + writer.println("Group info:"); + writer.indentedWriter() + .println("Id: {}", + Base64.getEncoder().encodeToString(messageReceived.getGroupId())); + } + if (messageReceived.getAttachments().size() > 0) { + writer.println("Attachments:"); + for (var attachment : messageReceived.getAttachments()) { + writer.println("- Stored plaintext in: {}", attachment); + } + } + writer.println(); + } catch (IOException e) { + e.printStackTrace(); } - if (syncReceived.getAttachments().size() > 0) { - System.out.println("Attachments: "); - for (var attachment : syncReceived.getAttachments()) { - System.out.println("- Stored plaintext in: " + attachment); + }); + + dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> { + try { + writer.println("Receipt from: {}", receiptReceived.getSender()); + writer.println("Timestamp: {}", DateUtils.formatTimestamp(receiptReceived.getTimestamp())); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> { + try { + writer.println("Sync Envelope from: {} to: {}", + syncReceived.getSource(), + syncReceived.getDestination()); + writer.println("Timestamp: {}", DateUtils.formatTimestamp(syncReceived.getTimestamp())); + writer.println("Body: {}", syncReceived.getMessage()); + if (syncReceived.getGroupId().length > 0) { + writer.println("Group info:"); + writer.indentedWriter() + .println("Id: {}", Base64.getEncoder().encodeToString(syncReceived.getGroupId())); + } + if (syncReceived.getAttachments().size() > 0) { + writer.println("Attachments:"); + for (var attachment : syncReceived.getAttachments()) { + writer.println("- Stored plaintext in: {}", attachment); + } } + writer.println(); + } catch (IOException e) { + e.printStackTrace(); } - System.out.println(); - } - }); + }); + } } catch (DBusException e) { e.printStackTrace(); return 2; diff --git a/src/main/java/org/asamk/signal/commands/SendCommand.java b/src/main/java/org/asamk/signal/commands/SendCommand.java index f1768b76..1976fb60 100644 --- a/src/main/java/org/asamk/signal/commands/SendCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendCommand.java @@ -5,11 +5,14 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.Signal; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.util.IOUtils; import org.asamk.signal.util.Util; import org.freedesktop.dbus.errors.UnknownObject; import org.freedesktop.dbus.exceptions.DBusExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.charset.Charset; @@ -20,6 +23,8 @@ import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException; public class SendCommand implements DbusCommand { + private final static Logger logger = LoggerFactory.getLogger(SendCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("recipient").help("Specify the recipients' phone number.").nargs("*"); @@ -90,18 +95,20 @@ public class SendCommand implements DbusCommand { attachments = List.of(); } + final var writer = new PlainTextWriterImpl(System.out); + if (groupIdString != null) { + byte[] groupId; try { - byte[] groupId; - try { - groupId = Util.decodeGroupId(groupIdString).serialize(); - } catch (GroupIdFormatException e) { - handleGroupIdFormatException(e); - return 1; - } + groupId = Util.decodeGroupId(groupIdString).serialize(); + } catch (GroupIdFormatException e) { + handleGroupIdFormatException(e); + return 1; + } + try { var timestamp = signal.sendGroupMessage(messageText, attachments, groupId); - System.out.println(timestamp); + writer.println("{}", timestamp); return 0; } catch (AssertionError e) { handleAssertionError(e); @@ -109,13 +116,16 @@ public class SendCommand implements DbusCommand { } catch (DBusExecutionException e) { System.err.println("Failed to send group message: " + e.getMessage()); return 2; + } catch (IOException e) { + e.printStackTrace(); + return 3; } } if (isNoteToSelf) { try { var timestamp = signal.sendNoteToSelfMessage(messageText, attachments); - System.out.println(timestamp); + writer.println("{}", timestamp); return 0; } catch (AssertionError e) { handleAssertionError(e); @@ -126,12 +136,15 @@ public class SendCommand implements DbusCommand { } catch (DBusExecutionException e) { System.err.println("Failed to send note to self message: " + e.getMessage()); return 2; + } catch (IOException e) { + e.printStackTrace(); + return 3; } } try { var timestamp = signal.sendMessage(messageText, attachments, recipients); - System.out.println(timestamp); + writer.println("{}", timestamp); return 0; } catch (AssertionError e) { handleAssertionError(e); @@ -145,6 +158,9 @@ public class SendCommand implements DbusCommand { } catch (DBusExecutionException e) { System.err.println("Failed to send message: " + e.getMessage()); return 2; + } catch (IOException e) { + e.printStackTrace(); + return 3; } } } diff --git a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java index 36d04185..bcae9d41 100644 --- a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java @@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; @@ -66,6 +67,8 @@ public class SendReactionCommand implements LocalCommand { final long targetTimestamp = ns.getLong("target_timestamp"); try { + final var writer = new PlainTextWriterImpl(System.out); + final Pair> results; if (groupIdString != null) { var groupId = Util.decodeGroupId(groupIdString); @@ -73,7 +76,7 @@ public class SendReactionCommand implements LocalCommand { } else { results = m.sendMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, recipients); } - return handleTimestampAndSendMessageResults(results.first(), results.second()); + return handleTimestampAndSendMessageResults(writer, results.first(), results.second()); } catch (IOException e) { handleIOException(e); return 3; diff --git a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java index 332bbe5e..fdb23ea1 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java @@ -4,10 +4,14 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.Signal; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.util.Util; import org.freedesktop.dbus.exceptions.DBusExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.IOException; import java.util.ArrayList; import java.util.Base64; import java.util.List; @@ -17,6 +21,8 @@ import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException; public class UpdateGroupCommand implements DbusCommand { + private final static Logger logger = LoggerFactory.getLogger(UpdateGroupCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("-g", "--group").help("Specify the recipient group ID."); @@ -27,6 +33,7 @@ public class UpdateGroupCommand implements DbusCommand { @Override public int handleCommand(final Namespace ns, final Signal signal) { + final var writer = new PlainTextWriterImpl(System.out); byte[] groupId = null; if (ns.getString("group") != null) { try { @@ -58,7 +65,12 @@ public class UpdateGroupCommand implements DbusCommand { try { var newGroupId = signal.updateGroup(groupId, groupName, groupMembers, groupAvatar); if (groupId.length != newGroupId.length) { - System.out.println("Creating new group \"" + Base64.getEncoder().encodeToString(newGroupId) + "\" …"); + try { + writer.println("Creating new group \"{}\" …", Base64.getEncoder().encodeToString(newGroupId)); + } catch (IOException e) { + e.printStackTrace(); + return 3; + } } return 0; } catch (AssertionError e) { diff --git a/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java b/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java index 94ba9e9c..9d72a6c5 100644 --- a/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java +++ b/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java @@ -3,14 +3,19 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.StickerPackInvalidException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; public class UploadStickerPackCommand implements LocalCommand { + private final static Logger logger = LoggerFactory.getLogger(UploadStickerPackCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("path") @@ -19,10 +24,11 @@ public class UploadStickerPackCommand implements LocalCommand { @Override public int handleCommand(final Namespace ns, final Manager m) { + final var writer = new PlainTextWriterImpl(System.out); try { var path = new File(ns.getString("path")); var url = m.uploadStickerPack(path); - System.out.println(url); + writer.println("{}", url); return 0; } catch (IOException e) { System.err.println("Upload error: " + e.getMessage()); diff --git a/src/main/java/org/asamk/signal/util/ErrorUtils.java b/src/main/java/org/asamk/signal/util/ErrorUtils.java index 65e41cc8..149b16c0 100644 --- a/src/main/java/org/asamk/signal/util/ErrorUtils.java +++ b/src/main/java/org/asamk/signal/util/ErrorUtils.java @@ -1,5 +1,6 @@ package org.asamk.signal.util; +import org.asamk.signal.PlainTextWriter; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; @@ -22,9 +23,13 @@ public class ErrorUtils { "If you use an Oracle JRE please check if you have unlimited strength crypto enabled, see README"); } - public static int handleTimestampAndSendMessageResults(long timestamp, List results) { + public static int handleTimestampAndSendMessageResults( + PlainTextWriter writer, + long timestamp, + List results + ) throws IOException { if (timestamp != 0) { - System.out.println(timestamp); + writer.println("{}", timestamp); } var errors = getErrorMessagesFromSendMessageResults(results); return handleSendMessageResultErrors(errors); -- 2.51.0 From 221d937eecca5c9b09a3bee7df812203b9927a56 Mon Sep 17 00:00:00 2001 From: AsamK Date: Mon, 22 Feb 2021 20:43:08 +0100 Subject: [PATCH 07/16] Add CommandException to abstract cli return codes for errors --- src/main/java/org/asamk/signal/App.java | 121 ++++++++---------- .../signal/JsonReceiveMessageHandler.java | 8 +- .../java/org/asamk/signal/JsonWriter.java | 16 ++- src/main/java/org/asamk/signal/Main.java | 29 ++++- .../org/asamk/signal/PlainTextWriter.java | 10 +- .../org/asamk/signal/PlainTextWriterImpl.java | 20 ++- .../asamk/signal/ReceiveMessageHandler.java | 2 +- .../signal/commands/AddDeviceCommand.java | 25 ++-- .../asamk/signal/commands/BlockCommand.java | 12 +- .../asamk/signal/commands/DaemonCommand.java | 12 +- .../asamk/signal/commands/DbusCommand.java | 7 +- .../signal/commands/ExtendedDbusCommand.java | 3 +- .../signal/commands/GetUserStatusCommand.java | 26 ++-- .../signal/commands/JoinGroupCommand.java | 37 ++---- .../asamk/signal/commands/LinkCommand.java | 22 ++-- .../signal/commands/ListContactsCommand.java | 14 +- .../signal/commands/ListDevicesCommand.java | 36 ++++-- .../signal/commands/ListGroupsCommand.java | 26 +--- .../commands/ListIdentitiesCommand.java | 49 +++---- .../asamk/signal/commands/LocalCommand.java | 3 +- .../signal/commands/MultiLocalCommand.java | 7 +- .../signal/commands/ProvisioningCommand.java | 3 +- .../signal/commands/QuitGroupCommand.java | 36 +++--- .../asamk/signal/commands/ReceiveCommand.java | 114 +++++++---------- .../signal/commands/RegisterCommand.java | 22 ++-- .../signal/commands/RegistrationCommand.java | 3 +- .../signal/commands/RemoveDeviceCommand.java | 8 +- .../signal/commands/RemovePinCommand.java | 12 +- .../asamk/signal/commands/SendCommand.java | 73 ++++------- .../signal/commands/SendContactsCommand.java | 12 +- .../signal/commands/SendReactionCommand.java | 56 ++++---- .../asamk/signal/commands/SetPinCommand.java | 12 +- .../asamk/signal/commands/TrustCommand.java | 30 ++--- .../asamk/signal/commands/UnblockCommand.java | 21 +-- .../signal/commands/UnregisterCommand.java | 8 +- .../signal/commands/UpdateAccountCommand.java | 8 +- .../signal/commands/UpdateContactCommand.java | 13 +- .../signal/commands/UpdateGroupCommand.java | 26 ++-- .../signal/commands/UpdateProfileCommand.java | 16 +-- .../commands/UploadStickerPackCommand.java | 15 ++- .../asamk/signal/commands/VerifyCommand.java | 29 +++-- .../commands/exceptions/CommandException.java | 8 ++ .../commands/exceptions/IOErrorException.java | 8 ++ .../exceptions/UnexpectedErrorException.java | 8 ++ .../UntrustedKeyErrorException.java | 8 ++ .../exceptions/UserErrorException.java | 8 ++ .../org/asamk/signal/util/ErrorUtils.java | 62 +++------ 47 files changed, 535 insertions(+), 569 deletions(-) create mode 100644 src/main/java/org/asamk/signal/commands/exceptions/CommandException.java create mode 100644 src/main/java/org/asamk/signal/commands/exceptions/IOErrorException.java create mode 100644 src/main/java/org/asamk/signal/commands/exceptions/UnexpectedErrorException.java create mode 100644 src/main/java/org/asamk/signal/commands/exceptions/UntrustedKeyErrorException.java create mode 100644 src/main/java/org/asamk/signal/commands/exceptions/UserErrorException.java diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index 5f0f1cdf..5b2c91c6 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -14,6 +14,9 @@ import org.asamk.signal.commands.LocalCommand; import org.asamk.signal.commands.MultiLocalCommand; import org.asamk.signal.commands.ProvisioningCommand; import org.asamk.signal.commands.RegistrationCommand; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.NotRegisteredException; import org.asamk.signal.manager.ProvisioningManager; @@ -29,9 +32,8 @@ import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; public class App { @@ -79,18 +81,16 @@ public class App { this.ns = ns; } - public int init() { + public void init() throws CommandException { var commandKey = ns.getString("command"); var command = Commands.getCommand(commandKey); if (command == null) { - logger.error("Command not implemented!"); - return 1; + throw new UserErrorException("Command not implemented!"); } OutputType outputType = ns.get("output"); if (!command.getSupportedOutputTypes().contains(outputType)) { - logger.error("Command doesn't support output type {}", outputType.toString()); - return 1; + throw new UserErrorException("Command doesn't support output type " + outputType.toString()); } var username = ns.getString("username"); @@ -99,7 +99,8 @@ public class App { final boolean useDbusSystem = ns.getBoolean("dbus_system"); if (useDbus || useDbusSystem) { // If username is null, it will connect to the default object path - return initDbusClient(command, username, useDbusSystem); + initDbusClient(command, username, useDbusSystem); + return; } final File dataPath; @@ -118,111 +119,102 @@ public class App { } if (!ServiceConfig.isSignalClientAvailable()) { - logger.error("Missing required native library dependency: libsignal-client"); - return 1; + throw new UserErrorException("Missing required native library dependency: libsignal-client"); } if (command instanceof ProvisioningCommand) { if (username != null) { - System.err.println("You cannot specify a username (phone number) when linking"); - return 1; + throw new UserErrorException("You cannot specify a username (phone number) when linking"); } - return handleProvisioningCommand((ProvisioningCommand) command, dataPath, serviceEnvironment); + handleProvisioningCommand((ProvisioningCommand) command, dataPath, serviceEnvironment); + return; } if (username == null) { var usernames = Manager.getAllLocalUsernames(dataPath); if (usernames.size() == 0) { - System.err.println("No local users found, you first need to register or link an account"); - return 1; + throw new UserErrorException("No local users found, you first need to register or link an account"); } if (command instanceof MultiLocalCommand) { - return handleMultiLocalCommand((MultiLocalCommand) command, dataPath, serviceEnvironment, usernames); + handleMultiLocalCommand((MultiLocalCommand) command, dataPath, serviceEnvironment, usernames); + return; } if (usernames.size() > 1) { - System.err.println("Multiple users found, you need to specify a username (phone number) with -u"); - return 1; + throw new UserErrorException( + "Multiple users found, you need to specify a username (phone number) with -u"); } username = usernames.get(0); } else if (!PhoneNumberFormatter.isValidNumber(username, null)) { - System.err.println("Invalid username (phone number), make sure you include the country code."); - return 1; + throw new UserErrorException("Invalid username (phone number), make sure you include the country code."); } if (command instanceof RegistrationCommand) { - return handleRegistrationCommand((RegistrationCommand) command, username, dataPath, serviceEnvironment); + handleRegistrationCommand((RegistrationCommand) command, username, dataPath, serviceEnvironment); + return; } if (!(command instanceof LocalCommand)) { - System.err.println("Command only works via dbus"); - return 1; + throw new UserErrorException("Command only works via dbus"); } - return handleLocalCommand((LocalCommand) command, username, dataPath, serviceEnvironment); + handleLocalCommand((LocalCommand) command, username, dataPath, serviceEnvironment); } - private int handleProvisioningCommand( + private void handleProvisioningCommand( final ProvisioningCommand command, final File dataPath, final ServiceEnvironment serviceEnvironment - ) { + ) throws CommandException { var pm = ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT); - return command.handleCommand(ns, pm); + command.handleCommand(ns, pm); } - private int handleRegistrationCommand( + private void handleRegistrationCommand( final RegistrationCommand command, final String username, final File dataPath, final ServiceEnvironment serviceEnvironment - ) { + ) throws CommandException { final RegistrationManager manager; try { manager = RegistrationManager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT); } catch (Throwable e) { - logger.error("Error loading or creating state file: {}", e.getMessage()); - return 2; + throw new UnexpectedErrorException("Error loading or creating state file: " + e.getMessage()); } try (var m = manager) { - return command.handleCommand(ns, m); + command.handleCommand(ns, m); } catch (IOException e) { - logger.error("Cleanup failed", e); - return 2; + logger.warn("Cleanup failed", e); } } - private int handleLocalCommand( + private void handleLocalCommand( final LocalCommand command, final String username, final File dataPath, final ServiceEnvironment serviceEnvironment - ) { + ) throws CommandException { try (var m = loadManager(username, dataPath, serviceEnvironment)) { - if (m == null) { - return 2; - } - - return command.handleCommand(ns, m); + command.handleCommand(ns, m); } catch (IOException e) { - logger.error("Cleanup failed", e); - return 2; + logger.warn("Cleanup failed", e); } } - private int handleMultiLocalCommand( + private void handleMultiLocalCommand( final MultiLocalCommand command, final File dataPath, final ServiceEnvironment serviceEnvironment, final List usernames - ) { - final var managers = usernames.stream() - .map(u -> loadManager(u, dataPath, serviceEnvironment)) - .filter(Objects::nonNull) - .collect(Collectors.toList()); + ) throws CommandException { + final var managers = new ArrayList(); + for (String u : usernames) { + managers.add(loadManager(u, dataPath, serviceEnvironment)); + } - var result = command.handleCommand(ns, managers); + command.handleCommand(ns, managers); for (var m : managers) { try { @@ -231,34 +223,32 @@ public class App { logger.warn("Cleanup failed", e); } } - return result; } private Manager loadManager( final String username, final File dataPath, final ServiceEnvironment serviceEnvironment - ) { + ) throws CommandException { Manager manager; try { manager = Manager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT); } catch (NotRegisteredException e) { - logger.error("User " + username + " is not registered."); - return null; + throw new UserErrorException("User " + username + " is not registered."); } catch (Throwable e) { - logger.error("Error loading state file for user " + username + ": {}", e.getMessage()); - return null; + throw new UnexpectedErrorException("Error loading state file for user " + username + ": " + e.getMessage()); } try { manager.checkAccountState(); } catch (IOException e) { - logger.error("Error while checking account " + username + ": {}", e.getMessage()); - return null; + throw new UnexpectedErrorException("Error while checking account " + username + ": " + e.getMessage()); } return manager; } - private int initDbusClient(final Command command, final String username, final boolean systemBus) { + private void initDbusClient( + final Command command, final String username, final boolean systemBus + ) throws CommandException { try { DBusConnection.DBusBusType busType; if (systemBus) { @@ -271,22 +261,21 @@ public class App { DbusConfig.getObjectPath(username), Signal.class); - return handleCommand(command, ts, dBusConn); + handleCommand(command, ts, dBusConn); } } catch (DBusException | IOException e) { logger.error("Dbus client failed", e); - return 2; + throw new UnexpectedErrorException("Dbus client failed"); } } - private int handleCommand(Command command, Signal ts, DBusConnection dBusConn) { + private void handleCommand(Command command, Signal ts, DBusConnection dBusConn) throws CommandException { if (command instanceof ExtendedDbusCommand) { - return ((ExtendedDbusCommand) command).handleCommand(ns, ts, dBusConn); + ((ExtendedDbusCommand) command).handleCommand(ns, ts, dBusConn); } else if (command instanceof DbusCommand) { - return ((DbusCommand) command).handleCommand(ns, ts); + ((DbusCommand) command).handleCommand(ns, ts); } else { - System.err.println("Command is not yet implemented via dbus"); - return 1; + throw new UserErrorException("Command is not yet implemented via dbus"); } } diff --git a/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java b/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java index 38657f5e..c8e1c24f 100644 --- a/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java @@ -8,7 +8,6 @@ import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; -import java.io.IOException; import java.util.HashMap; public class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler { @@ -32,10 +31,7 @@ public class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler if (envelope != null) { object.put("envelope", new JsonMessageEnvelope(envelope, content, m)); } - try { - jsonWriter.write(object); - } catch (IOException e) { - logger.error("Failed to write json object: {}", e.getMessage()); - } + + jsonWriter.write(object); } } diff --git a/src/main/java/org/asamk/signal/JsonWriter.java b/src/main/java/org/asamk/signal/JsonWriter.java index 8aed4487..e7549adf 100644 --- a/src/main/java/org/asamk/signal/JsonWriter.java +++ b/src/main/java/org/asamk/signal/JsonWriter.java @@ -26,14 +26,18 @@ public class JsonWriter { objectMapper.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); } - public void write(final Object object) throws IOException { + public void write(final Object object) { try { - objectMapper.writeValue(writer, object); - } catch (JsonProcessingException e) { - // Some issue with json serialization, probably caused by a bug + try { + objectMapper.writeValue(writer, object); + } catch (JsonProcessingException e) { + // Some issue with json serialization, probably caused by a bug + throw new AssertionError(e); + } + writer.write(System.lineSeparator()); + writer.flush(); + } catch (IOException e) { throw new AssertionError(e); } - writer.write(System.lineSeparator()); - writer.flush(); } } diff --git a/src/main/java/org/asamk/signal/Main.java b/src/main/java/org/asamk/signal/Main.java index 88ae06ca..775b5223 100644 --- a/src/main/java/org/asamk/signal/Main.java +++ b/src/main/java/org/asamk/signal/Main.java @@ -21,6 +21,11 @@ import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.ArgumentParserException; import net.sourceforge.argparse4j.inf.Namespace; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.LibSignalLogger; import org.asamk.signal.util.SecurityProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -39,8 +44,14 @@ public class Main { var ns = parser.parseArgsOrFail(args); - var res = new App(ns).init(); - System.exit(res); + int status = 0; + try { + new App(ns).init(); + } catch (CommandException e) { + System.err.println(e.getMessage()); + status = getStatusForError(e); + } + System.exit(status); } private static void installSecurityProviderWorkaround() { @@ -78,4 +89,18 @@ public class Main { System.setProperty("org.slf4j.simpleLogger.showDateTime", "false"); } } + + private static int getStatusForError(final CommandException e) { + if (e instanceof UserErrorException) { + return 1; + } else if (e instanceof UnexpectedErrorException) { + return 2; + } else if (e instanceof IOErrorException) { + return 3; + } else if (e instanceof UntrustedKeyErrorException) { + return 4; + } else { + return 2; + } + } } diff --git a/src/main/java/org/asamk/signal/PlainTextWriter.java b/src/main/java/org/asamk/signal/PlainTextWriter.java index 91a4dbba..de738de9 100644 --- a/src/main/java/org/asamk/signal/PlainTextWriter.java +++ b/src/main/java/org/asamk/signal/PlainTextWriter.java @@ -1,23 +1,21 @@ package org.asamk.signal; -import java.io.IOException; - public interface PlainTextWriter { - void println(String format, Object... args) throws IOException; + void println(String format, Object... args); PlainTextWriter indentedWriter(); - default void println() throws IOException { + default void println() { println(""); } - default void indent(final WriterConsumer subWriter) throws IOException { + default void indent(final WriterConsumer subWriter) { subWriter.consume(indentedWriter()); } interface WriterConsumer { - void consume(PlainTextWriter writer) throws IOException; + void consume(PlainTextWriter writer); } } diff --git a/src/main/java/org/asamk/signal/PlainTextWriterImpl.java b/src/main/java/org/asamk/signal/PlainTextWriterImpl.java index d6536481..bb18b7f3 100644 --- a/src/main/java/org/asamk/signal/PlainTextWriterImpl.java +++ b/src/main/java/org/asamk/signal/PlainTextWriterImpl.java @@ -19,12 +19,16 @@ public final class PlainTextWriterImpl implements PlainTextWriter { } @Override - public void println(String format, Object... args) throws IOException { + public void println(String format, Object... args) { final var message = MessageFormatter.arrayFormat(format, args).getMessage(); - writer.write(message); - writer.write(System.lineSeparator()); - writer.flush(); + try { + writer.write(message); + writer.write(System.lineSeparator()); + writer.flush(); + } catch (IOException e) { + throw new AssertionError(e); + } } @Override @@ -51,8 +55,12 @@ public final class PlainTextWriterImpl implements PlainTextWriter { } @Override - public void println(final String format, final Object... args) throws IOException { - writer.write(spaces); + public void println(final String format, final Object... args) { + try { + writer.write(spaces); + } catch (IOException e) { + throw new AssertionError(e); + } plainTextWriter.println(format, args); } diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java index 8c75fcba..6df283f3 100644 --- a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java @@ -630,7 +630,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { writer.println("- {}: {} (length: {})", formatContact(address), mention.getStart(), mention.getLength()); } - private void printAttachment(PlainTextWriter writer, SignalServiceAttachment attachment) throws IOException { + private void printAttachment(PlainTextWriter writer, SignalServiceAttachment attachment) { writer.println("Content-Type: {}", attachment.getContentType()); writer.println("Type: {}", attachment.isPointer() ? "Pointer" : attachment.isStream() ? "Stream" : ""); if (attachment.isPointer()) { diff --git a/src/main/java/org/asamk/signal/commands/AddDeviceCommand.java b/src/main/java/org/asamk/signal/commands/AddDeviceCommand.java index c5d18ab1..cf993e6d 100644 --- a/src/main/java/org/asamk/signal/commands/AddDeviceCommand.java +++ b/src/main/java/org/asamk/signal/commands/AddDeviceCommand.java @@ -3,7 +3,13 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.InvalidKeyException; import java.io.IOException; @@ -14,6 +20,8 @@ import static org.asamk.signal.util.ErrorUtils.handleAssertionError; public class AddDeviceCommand implements LocalCommand { + private final static Logger logger = LoggerFactory.getLogger(AddDeviceCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("--uri") @@ -22,19 +30,20 @@ public class AddDeviceCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { try { m.addDeviceLink(new URI(ns.getString("uri"))); - return 0; } catch (IOException e) { - e.printStackTrace(); - return 3; - } catch (InvalidKeyException | URISyntaxException e) { - e.printStackTrace(); - return 2; + logger.error("Add device link failed", e); + throw new IOErrorException("Add device link failed"); + } catch (URISyntaxException e) { + throw new UserErrorException("Device link uri has invalid format: {}" + e.getMessage()); + } catch (InvalidKeyException e) { + logger.error("Add device link failed", e); + throw new UnexpectedErrorException("Add device link failed."); } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } } } diff --git a/src/main/java/org/asamk/signal/commands/BlockCommand.java b/src/main/java/org/asamk/signal/commands/BlockCommand.java index 9dff25c6..98fce667 100644 --- a/src/main/java/org/asamk/signal/commands/BlockCommand.java +++ b/src/main/java/org/asamk/signal/commands/BlockCommand.java @@ -7,10 +7,14 @@ import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.util.InvalidNumberException; public class BlockCommand implements LocalCommand { + private final static Logger logger = LoggerFactory.getLogger(BlockCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("contact").help("Contact number").nargs("*"); @@ -19,12 +23,12 @@ public class BlockCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) { for (var contact_number : ns.getList("contact")) { try { m.setContactBlocked(contact_number, true); } catch (InvalidNumberException e) { - System.err.println(e.getMessage()); + logger.warn("Invalid number {}: {}", contact_number, e.getMessage()); } } @@ -34,11 +38,9 @@ public class BlockCommand implements LocalCommand { var groupId = Util.decodeGroupId(groupIdString); m.setGroupBlocked(groupId, true); } catch (GroupIdFormatException | GroupNotFoundException e) { - System.err.println(e.getMessage()); + logger.warn("Invalid group id {}: {}", groupIdString, e.getMessage()); } } } - - return 0; } } diff --git a/src/main/java/org/asamk/signal/commands/DaemonCommand.java b/src/main/java/org/asamk/signal/commands/DaemonCommand.java index 6ee4f316..8d26e452 100644 --- a/src/main/java/org/asamk/signal/commands/DaemonCommand.java +++ b/src/main/java/org/asamk/signal/commands/DaemonCommand.java @@ -8,6 +8,8 @@ import org.asamk.signal.DbusConfig; import org.asamk.signal.DbusReceiveMessageHandler; import org.asamk.signal.JsonDbusReceiveMessageHandler; import org.asamk.signal.OutputType; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; import org.asamk.signal.dbus.DbusSignalImpl; import org.asamk.signal.manager.Manager; import org.freedesktop.dbus.connections.impl.DBusConnection; @@ -44,7 +46,7 @@ public class DaemonCommand implements MultiLocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed @@ -71,15 +73,14 @@ public class DaemonCommand implements MultiLocalCommand { t.join(); } catch (InterruptedException ignored) { } - return 0; } catch (DBusException | IOException e) { logger.error("Dbus command failed", e); - return 2; + throw new UnexpectedErrorException("Dbus command failed"); } } @Override - public int handleCommand(final Namespace ns, final List managers) { + public void handleCommand(final Namespace ns, final List managers) throws CommandException { var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed @@ -112,10 +113,9 @@ public class DaemonCommand implements MultiLocalCommand { } catch (InterruptedException ignored) { } } - return 0; } catch (DBusException | IOException e) { logger.error("Dbus command failed", e); - return 2; + throw new UnexpectedErrorException("Dbus command failed"); } } diff --git a/src/main/java/org/asamk/signal/commands/DbusCommand.java b/src/main/java/org/asamk/signal/commands/DbusCommand.java index 1b3a0268..e4c78c84 100644 --- a/src/main/java/org/asamk/signal/commands/DbusCommand.java +++ b/src/main/java/org/asamk/signal/commands/DbusCommand.java @@ -3,14 +3,15 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import org.asamk.Signal; +import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.dbus.DbusSignalImpl; import org.asamk.signal.manager.Manager; public interface DbusCommand extends LocalCommand { - int handleCommand(Namespace ns, Signal signal); + void handleCommand(Namespace ns, Signal signal) throws CommandException; - default int handleCommand(final Namespace ns, final Manager m) { - return handleCommand(ns, new DbusSignalImpl(m)); + default void handleCommand(final Namespace ns, final Manager m) throws CommandException { + handleCommand(ns, new DbusSignalImpl(m)); } } diff --git a/src/main/java/org/asamk/signal/commands/ExtendedDbusCommand.java b/src/main/java/org/asamk/signal/commands/ExtendedDbusCommand.java index f9cd9de8..1d454f4d 100644 --- a/src/main/java/org/asamk/signal/commands/ExtendedDbusCommand.java +++ b/src/main/java/org/asamk/signal/commands/ExtendedDbusCommand.java @@ -3,9 +3,10 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import org.asamk.Signal; +import org.asamk.signal.commands.exceptions.CommandException; import org.freedesktop.dbus.connections.impl.DBusConnection; public interface ExtendedDbusCommand extends Command { - int handleCommand(Namespace ns, Signal signal, DBusConnection dbusconnection); + void handleCommand(Namespace ns, Signal signal, DBusConnection dbusconnection) throws CommandException; } diff --git a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java index 07de8321..69140b23 100644 --- a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java +++ b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java @@ -7,6 +7,8 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputType; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.manager.Manager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +38,7 @@ public class GetUserStatusCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { // Setup the json object mapper var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); @@ -50,8 +52,8 @@ public class GetUserStatusCommand implements LocalCommand { try { registered = m.areUsersRegistered(new HashSet<>(ns.getList("number"))); } catch (IOException e) { - System.err.println("Unable to check if users are registered"); - return 3; + logger.debug("Failed to check registered users", e); + throw new IOErrorException("Unable to check if users are registered"); } // Output @@ -63,26 +65,14 @@ public class GetUserStatusCommand implements LocalCommand { .map(entry -> new JsonUserStatus(entry.getKey(), entry.getValue())) .collect(Collectors.toList()); - try { - jsonWriter.write(jsonUserStatuses); - } catch (IOException e) { - logger.error("Failed to write json object: {}", e.getMessage()); - return 3; - } + jsonWriter.write(jsonUserStatuses); } else { final var writer = new PlainTextWriterImpl(System.out); - try { - for (var entry : registered.entrySet()) { - writer.println("{}: {}", entry.getKey(), entry.getValue()); - } - } catch (IOException e) { - e.printStackTrace(); - return 3; + for (var entry : registered.entrySet()) { + writer.println("{}: {}", entry.getKey(), entry.getValue()); } } - - return 0; } private static final class JsonUserStatus { diff --git a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java index 7f1cb0b0..e59ecec6 100644 --- a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java @@ -4,46 +4,42 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.freedesktop.dbus.exceptions.DBusExecutionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; import org.whispersystems.signalservice.internal.push.exceptions.GroupPatchNotAcceptedException; import java.io.IOException; import static org.asamk.signal.util.ErrorUtils.handleAssertionError; -import static org.asamk.signal.util.ErrorUtils.handleIOException; import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResults; public class JoinGroupCommand implements LocalCommand { - private final static Logger logger = LoggerFactory.getLogger(JoinGroupCommand.class); - @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("--uri").required(true).help("Specify the uri with the group invitation link."); } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { final GroupInviteLinkUrl linkUrl; var uri = ns.getString("uri"); try { linkUrl = GroupInviteLinkUrl.fromUri(uri); } catch (GroupInviteLinkUrl.InvalidGroupLinkException e) { - System.err.println("Group link is invalid: " + e.getMessage()); - return 1; + throw new UserErrorException("Group link is invalid: " + e.getMessage()); } catch (GroupInviteLinkUrl.UnknownGroupLinkVersionException e) { - System.err.println("Group link was created with an incompatible version: " + e.getMessage()); - return 1; + throw new UserErrorException("Group link was created with an incompatible version: " + e.getMessage()); } if (linkUrl == null) { - System.err.println("Link is not a signal group invitation link"); - return 1; + throw new UserErrorException("Link is not a signal group invitation link"); } try { @@ -56,23 +52,18 @@ public class JoinGroupCommand implements LocalCommand { } else { writer.println("Joined group \"{}\"", newGroupId.toBase64()); } - return handleTimestampAndSendMessageResults(writer, 0, results.second()); + handleTimestampAndSendMessageResults(writer, 0, results.second()); } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (GroupPatchNotAcceptedException e) { - System.err.println("Failed to join group, maybe already a member"); - return 1; + throw new UserErrorException("Failed to join group, maybe already a member"); } catch (IOException e) { - e.printStackTrace(); - handleIOException(e); - return 3; + throw new IOErrorException("Failed to send message: " + e.getMessage()); } catch (DBusExecutionException e) { - System.err.println("Failed to send message: " + e.getMessage()); - return 2; + throw new UnexpectedErrorException("Failed to send message: " + e.getMessage()); } catch (GroupLinkNotActiveException e) { - System.err.println("Group link is not valid: " + e.getMessage()); - return 1; + throw new UserErrorException("Group link is not valid: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/LinkCommand.java b/src/main/java/org/asamk/signal/commands/LinkCommand.java index fe580916..34775773 100644 --- a/src/main/java/org/asamk/signal/commands/LinkCommand.java +++ b/src/main/java/org/asamk/signal/commands/LinkCommand.java @@ -4,6 +4,10 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.ProvisioningManager; import org.asamk.signal.manager.UserAlreadyExists; import org.slf4j.Logger; @@ -25,7 +29,7 @@ public class LinkCommand implements ProvisioningCommand { } @Override - public int handleCommand(final Namespace ns, final ProvisioningManager m) { + public void handleCommand(final Namespace ns, final ProvisioningManager m) throws CommandException { final var writer = new PlainTextWriterImpl(System.out); var deviceName = ns.getString("name"); @@ -37,25 +41,21 @@ public class LinkCommand implements ProvisioningCommand { var username = m.finishDeviceLink(deviceName); writer.println("Associated with: {}", username); } catch (TimeoutException e) { - System.err.println("Link request timed out, please try again."); - return 3; + throw new UserErrorException("Link request timed out, please try again."); } catch (IOException e) { - System.err.println("Link request error: " + e.getMessage()); - return 3; + throw new IOErrorException("Link request error: " + e.getMessage()); } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (InvalidKeyException e) { - e.printStackTrace(); - return 2; + logger.debug("Finish device link failed", e); + throw new UnexpectedErrorException("Invalid key: " + e.getMessage()); } catch (UserAlreadyExists e) { - System.err.println("The user " + throw new UserErrorException("The user " + e.getUsername() + " already exists\nDelete \"" + e.getFileName() + "\" before trying again."); - return 1; } - return 0; } } diff --git a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java index 6609ec60..4b27e17d 100644 --- a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java @@ -6,8 +6,6 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.manager.Manager; -import java.io.IOException; - public class ListContactsCommand implements LocalCommand { @Override @@ -15,18 +13,12 @@ public class ListContactsCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) { final var writer = new PlainTextWriterImpl(System.out); var contacts = m.getContacts(); - try { - for (var c : contacts) { - writer.println("Number: {} Name: {} Blocked: {}", c.number, c.name, c.blocked); - } - } catch (IOException e) { - e.printStackTrace(); - return 3; + for (var c : contacts) { + writer.println("Number: {} Name: {} Blocked: {}", c.number, c.name, c.blocked); } - return 0; } } diff --git a/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java b/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java index f2037239..7165d07c 100644 --- a/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java @@ -4,34 +4,44 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.util.DateUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo; import java.io.IOException; +import java.util.List; public class ListDevicesCommand implements LocalCommand { + private final static Logger logger = LoggerFactory.getLogger(ListDevicesCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { final var writer = new PlainTextWriterImpl(System.out); + + List devices; try { - var devices = m.getLinkedDevices(); - for (var d : devices) { - writer.println("- Device {}{}:", d.getId(), (d.getId() == m.getDeviceId() ? " (this device)" : "")); - writer.indent(w -> { - w.println("Name: {}", d.getName()); - w.println("Created: {}", DateUtils.formatTimestamp(d.getCreated())); - w.println("Last seen: {}", DateUtils.formatTimestamp(d.getLastSeen())); - }); - } - return 0; + devices = m.getLinkedDevices(); } catch (IOException e) { - e.printStackTrace(); - return 3; + logger.debug("Failed to get linked devices", e); + throw new IOErrorException("Failed to get linked devices: " + e.getMessage()); + } + + for (var d : devices) { + writer.println("- Device {}{}:", d.getId(), (d.getId() == m.getDeviceId() ? " (this device)" : "")); + writer.indent(w -> { + w.println("Name: {}", d.getName()); + w.println("Created: {}", DateUtils.formatTimestamp(d.getCreated())); + w.println("Last seen: {}", DateUtils.formatTimestamp(d.getLastSeen())); + }); } } } diff --git a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java index 477d56a1..a547cc15 100644 --- a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java @@ -8,13 +8,13 @@ import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputType; import org.asamk.signal.PlainTextWriter; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.storage.groups.GroupInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.push.SignalServiceAddress; -import java.io.IOException; import java.util.ArrayList; import java.util.Set; import java.util.stream.Collectors; @@ -32,7 +32,7 @@ public class ListGroupsCommand implements LocalCommand { private static void printGroupPlainText( PlainTextWriter writer, Manager m, GroupInfo group, boolean detailed - ) throws IOException { + ) { if (detailed) { final var groupInviteLink = group.getGroupInviteLink(); @@ -70,7 +70,7 @@ public class ListGroupsCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { if (ns.get("output") == OutputType.JSON) { final var jsonWriter = new JsonWriter(System.out); @@ -88,28 +88,14 @@ public class ListGroupsCommand implements LocalCommand { groupInviteLink == null ? null : groupInviteLink.getUrl())); } - try { - jsonWriter.write(jsonGroups); - } catch (IOException e) { - logger.error("Failed to write json object: {}", e.getMessage()); - return 3; - } - - return 0; + jsonWriter.write(jsonGroups); } else { final var writer = new PlainTextWriterImpl(System.out); boolean detailed = ns.getBoolean("detailed"); - try { - for (var group : m.getGroups()) { - printGroupPlainText(writer, m, group, detailed); - } - } catch (IOException e) { - e.printStackTrace(); - return 3; + for (var group : m.getGroups()) { + printGroupPlainText(writer, m, group, detailed); } } - - return 0; } private static final class JsonGroup { diff --git a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java index 1f1b6258..dc2d92fb 100644 --- a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java @@ -5,6 +5,8 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.PlainTextWriter; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.storage.protocol.IdentityInfo; import org.asamk.signal.util.Hex; @@ -13,7 +15,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.util.InvalidNumberException; -import java.io.IOException; +import java.util.List; public class ListIdentitiesCommand implements LocalCommand { @@ -21,16 +23,12 @@ public class ListIdentitiesCommand implements LocalCommand { private static void printIdentityFingerprint(PlainTextWriter writer, Manager m, IdentityInfo theirId) { var digits = Util.formatSafetyNumber(m.computeSafetyNumber(theirId.getAddress(), theirId.getIdentityKey())); - try { - writer.println("{}: {} Added: {} Fingerprint: {} Safety Number: {}", - theirId.getAddress().getNumber().orNull(), - theirId.getTrustLevel(), - theirId.getDateAdded(), - Hex.toString(theirId.getFingerprint()), - digits); - } catch (IOException e) { - e.printStackTrace(); - } + writer.println("{}: {} Added: {} Fingerprint: {} Safety Number: {}", + theirId.getAddress().getNumber().orNull(), + theirId.getTrustLevel(), + theirId.getDateAdded(), + Hex.toString(theirId.getFingerprint()), + digits); } @Override @@ -39,24 +37,27 @@ public class ListIdentitiesCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { final var writer = new PlainTextWriterImpl(System.out); - if (ns.get("number") == null) { + var number = ns.getString("number"); + + if (number == null) { for (var identity : m.getIdentities()) { printIdentityFingerprint(writer, m, identity); } - } else { - var number = ns.getString("number"); - try { - var identities = m.getIdentities(number); - for (var id : identities) { - printIdentityFingerprint(writer, m, id); - } - } catch (InvalidNumberException e) { - System.err.println("Invalid number: " + e.getMessage()); - } + return; + } + + List identities; + try { + identities = m.getIdentities(number); + } catch (InvalidNumberException e) { + throw new UserErrorException("Invalid number: " + e.getMessage()); + } + + for (var id : identities) { + printIdentityFingerprint(writer, m, id); } - return 0; } } diff --git a/src/main/java/org/asamk/signal/commands/LocalCommand.java b/src/main/java/org/asamk/signal/commands/LocalCommand.java index 7bcb1a4b..a7c64dc1 100644 --- a/src/main/java/org/asamk/signal/commands/LocalCommand.java +++ b/src/main/java/org/asamk/signal/commands/LocalCommand.java @@ -2,9 +2,10 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; +import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.manager.Manager; public interface LocalCommand extends Command { - int handleCommand(Namespace ns, Manager m); + void handleCommand(Namespace ns, Manager m) throws CommandException; } diff --git a/src/main/java/org/asamk/signal/commands/MultiLocalCommand.java b/src/main/java/org/asamk/signal/commands/MultiLocalCommand.java index e8ee8e1d..2a8457bd 100644 --- a/src/main/java/org/asamk/signal/commands/MultiLocalCommand.java +++ b/src/main/java/org/asamk/signal/commands/MultiLocalCommand.java @@ -2,16 +2,17 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; +import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.manager.Manager; import java.util.List; public interface MultiLocalCommand extends LocalCommand { - int handleCommand(Namespace ns, List m); + void handleCommand(Namespace ns, List m) throws CommandException; @Override - default int handleCommand(final Namespace ns, final Manager m) { - return handleCommand(ns, List.of(m)); + default void handleCommand(final Namespace ns, final Manager m) throws CommandException { + handleCommand(ns, List.of(m)); } } diff --git a/src/main/java/org/asamk/signal/commands/ProvisioningCommand.java b/src/main/java/org/asamk/signal/commands/ProvisioningCommand.java index 12a612ff..354e4af3 100644 --- a/src/main/java/org/asamk/signal/commands/ProvisioningCommand.java +++ b/src/main/java/org/asamk/signal/commands/ProvisioningCommand.java @@ -2,9 +2,10 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; +import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.manager.ProvisioningManager; public interface ProvisioningCommand extends Command { - int handleCommand(Namespace ns, ProvisioningManager m); + void handleCommand(Namespace ns, ProvisioningManager m) throws CommandException; } diff --git a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java index cdbccf19..d8a86585 100644 --- a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java @@ -4,7 +4,11 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; @@ -13,10 +17,6 @@ import org.asamk.signal.util.Util; import java.io.IOException; import static org.asamk.signal.util.ErrorUtils.handleAssertionError; -import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException; -import static org.asamk.signal.util.ErrorUtils.handleGroupNotFoundException; -import static org.asamk.signal.util.ErrorUtils.handleIOException; -import static org.asamk.signal.util.ErrorUtils.handleNotAGroupMemberException; import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResults; public class QuitGroupCommand implements LocalCommand { @@ -27,28 +27,28 @@ public class QuitGroupCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { + final var writer = new PlainTextWriterImpl(System.out); + + final GroupId groupId; try { - final var writer = new PlainTextWriterImpl(System.out); + groupId = Util.decodeGroupId(ns.getString("group")); + } catch (GroupIdFormatException e) { + throw new UserErrorException("Invalid group id:" + e.getMessage()); + } - final var groupId = Util.decodeGroupId(ns.getString("group")); + try { final var results = m.sendQuitGroupMessage(groupId); - return handleTimestampAndSendMessageResults(writer, results.first(), results.second()); + handleTimestampAndSendMessageResults(writer, results.first(), results.second()); } catch (IOException e) { - handleIOException(e); - return 3; + throw new IOErrorException("Failed to send message: " + e.getMessage()); } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (GroupNotFoundException e) { - handleGroupNotFoundException(e); - return 1; + throw new UserErrorException("Failed to send to group: " + e.getMessage()); } catch (NotAGroupMemberException e) { - handleNotAGroupMemberException(e); - return 1; - } catch (GroupIdFormatException e) { - handleGroupIdFormatException(e); - return 1; + throw new UserErrorException("Failed to send to group: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java index 834bc5eb..8612a71b 100644 --- a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java +++ b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java @@ -10,6 +10,9 @@ import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputType; import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.ReceiveMessageHandler; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; import org.asamk.signal.json.JsonMessageEnvelope; import org.asamk.signal.manager.Manager; import org.asamk.signal.util.DateUtils; @@ -48,7 +51,9 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { return Set.of(OutputType.PLAIN_TEXT, OutputType.JSON); } - public int handleCommand(final Namespace ns, final Signal signal, DBusConnection dbusconnection) { + public void handleCommand( + final Namespace ns, final Signal signal, DBusConnection dbusconnection + ) throws CommandException { var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed @@ -63,106 +68,81 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> { var envelope = new JsonMessageEnvelope(messageReceived); final var object = Map.of("envelope", envelope); - try { - jsonWriter.write(object); - } catch (IOException e) { - logger.error("Failed to write json object: {}", e.getMessage()); - } + jsonWriter.write(object); }); dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> { var envelope = new JsonMessageEnvelope(receiptReceived); final var object = Map.of("envelope", envelope); - try { - jsonWriter.write(object); - } catch (IOException e) { - logger.error("Failed to write json object: {}", e.getMessage()); - } + jsonWriter.write(object); }); dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> { var envelope = new JsonMessageEnvelope(syncReceived); final var object = Map.of("envelope", envelope); - try { - jsonWriter.write(object); - } catch (IOException e) { - logger.error("Failed to write json object: {}", e.getMessage()); - } + jsonWriter.write(object); }); } else { final var writer = new PlainTextWriterImpl(System.out); dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> { - try { - writer.println("Envelope from: {}", messageReceived.getSender()); - writer.println("Timestamp: {}", DateUtils.formatTimestamp(messageReceived.getTimestamp())); - writer.println("Body: {}", messageReceived.getMessage()); - if (messageReceived.getGroupId().length > 0) { - writer.println("Group info:"); - writer.indentedWriter() - .println("Id: {}", - Base64.getEncoder().encodeToString(messageReceived.getGroupId())); - } - if (messageReceived.getAttachments().size() > 0) { - writer.println("Attachments:"); - for (var attachment : messageReceived.getAttachments()) { - writer.println("- Stored plaintext in: {}", attachment); - } + writer.println("Envelope from: {}", messageReceived.getSender()); + writer.println("Timestamp: {}", DateUtils.formatTimestamp(messageReceived.getTimestamp())); + writer.println("Body: {}", messageReceived.getMessage()); + if (messageReceived.getGroupId().length > 0) { + writer.println("Group info:"); + writer.indentedWriter() + .println("Id: {}", Base64.getEncoder().encodeToString(messageReceived.getGroupId())); + } + if (messageReceived.getAttachments().size() > 0) { + writer.println("Attachments:"); + for (var attachment : messageReceived.getAttachments()) { + writer.println("- Stored plaintext in: {}", attachment); } - writer.println(); - } catch (IOException e) { - e.printStackTrace(); } + writer.println(); }); dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> { - try { - writer.println("Receipt from: {}", receiptReceived.getSender()); - writer.println("Timestamp: {}", DateUtils.formatTimestamp(receiptReceived.getTimestamp())); - } catch (IOException e) { - e.printStackTrace(); - } + writer.println("Receipt from: {}", receiptReceived.getSender()); + writer.println("Timestamp: {}", DateUtils.formatTimestamp(receiptReceived.getTimestamp())); }); dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> { - try { - writer.println("Sync Envelope from: {} to: {}", - syncReceived.getSource(), - syncReceived.getDestination()); - writer.println("Timestamp: {}", DateUtils.formatTimestamp(syncReceived.getTimestamp())); - writer.println("Body: {}", syncReceived.getMessage()); - if (syncReceived.getGroupId().length > 0) { - writer.println("Group info:"); - writer.indentedWriter() - .println("Id: {}", Base64.getEncoder().encodeToString(syncReceived.getGroupId())); - } - if (syncReceived.getAttachments().size() > 0) { - writer.println("Attachments:"); - for (var attachment : syncReceived.getAttachments()) { - writer.println("- Stored plaintext in: {}", attachment); - } + writer.println("Sync Envelope from: {} to: {}", + syncReceived.getSource(), + syncReceived.getDestination()); + writer.println("Timestamp: {}", DateUtils.formatTimestamp(syncReceived.getTimestamp())); + writer.println("Body: {}", syncReceived.getMessage()); + if (syncReceived.getGroupId().length > 0) { + writer.println("Group info:"); + writer.indentedWriter() + .println("Id: {}", Base64.getEncoder().encodeToString(syncReceived.getGroupId())); + } + if (syncReceived.getAttachments().size() > 0) { + writer.println("Attachments:"); + for (var attachment : syncReceived.getAttachments()) { + writer.println("- Stored plaintext in: {}", attachment); } - writer.println(); - } catch (IOException e) { - e.printStackTrace(); } + writer.println(); }); } } catch (DBusException e) { - e.printStackTrace(); - return 2; + logger.error("Dbus client failed", e); + throw new UnexpectedErrorException("Dbus client failed"); } while (true) { try { Thread.sleep(10000); - } catch (InterruptedException e) { - return 0; + } catch (InterruptedException ignored) { + return; } } } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json"); // TODO delete later when "json" variable is removed @@ -187,13 +167,11 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand { returnOnTimeout, ignoreAttachments, handler); - return 0; } catch (IOException e) { - System.err.println("Error while receiving messages: " + e.getMessage()); - return 3; + throw new IOErrorException("Error while receiving messages: " + e.getMessage()); } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } } } diff --git a/src/main/java/org/asamk/signal/commands/RegisterCommand.java b/src/main/java/org/asamk/signal/commands/RegisterCommand.java index d656fe0e..a4c613af 100644 --- a/src/main/java/org/asamk/signal/commands/RegisterCommand.java +++ b/src/main/java/org/asamk/signal/commands/RegisterCommand.java @@ -4,6 +4,9 @@ import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.RegistrationManager; import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException; @@ -21,26 +24,25 @@ public class RegisterCommand implements RegistrationCommand { } @Override - public int handleCommand(final Namespace ns, final RegistrationManager m) { + public void handleCommand(final Namespace ns, final RegistrationManager m) throws CommandException { final boolean voiceVerification = ns.getBoolean("voice"); final var captcha = ns.getString("captcha"); try { m.register(voiceVerification, captcha); - return 0; } catch (CaptchaRequiredException e) { + String message; if (captcha == null) { - System.err.println("Captcha required for verification, use --captcha CAPTCHA"); - System.err.println("To get the token, go to https://signalcaptchas.org/registration/generate.html"); - System.err.println("Check the developer tools (F12) console for a failed redirect to signalcaptcha://"); - System.err.println("Everything after signalcaptcha:// is the captcha token."); + message = "Captcha required for verification, use --captcha CAPTCHA\n" + + "To get the token, go to https://signalcaptchas.org/registration/generate.html\n" + + "Check the developer tools (F12) console for a failed redirect to signalcaptcha://\n" + + "Everything after signalcaptcha:// is the captcha token."; } else { - System.err.println("Invalid captcha given."); + message = "Invalid captcha given."; } - return 1; + throw new UserErrorException(message); } catch (IOException e) { - System.err.println("Request verify error: " + e.getMessage()); - return 3; + throw new IOErrorException("Request verify error: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/RegistrationCommand.java b/src/main/java/org/asamk/signal/commands/RegistrationCommand.java index 8683570f..425ac71d 100644 --- a/src/main/java/org/asamk/signal/commands/RegistrationCommand.java +++ b/src/main/java/org/asamk/signal/commands/RegistrationCommand.java @@ -2,9 +2,10 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; +import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.manager.RegistrationManager; public interface RegistrationCommand extends Command { - int handleCommand(Namespace ns, RegistrationManager m); + void handleCommand(Namespace ns, RegistrationManager m) throws CommandException; } diff --git a/src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java b/src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java index 78d14bbd..c9be92e8 100644 --- a/src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java +++ b/src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java @@ -3,6 +3,8 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.manager.Manager; import java.io.IOException; @@ -18,14 +20,12 @@ public class RemoveDeviceCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { try { int deviceId = ns.getInt("deviceId"); m.removeLinkedDevices(deviceId); - return 0; } catch (IOException e) { - e.printStackTrace(); - return 3; + throw new IOErrorException("Error while removing device: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/RemovePinCommand.java b/src/main/java/org/asamk/signal/commands/RemovePinCommand.java index 52b111ea..03d8d7cb 100644 --- a/src/main/java/org/asamk/signal/commands/RemovePinCommand.java +++ b/src/main/java/org/asamk/signal/commands/RemovePinCommand.java @@ -3,6 +3,9 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; import org.asamk.signal.manager.Manager; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException; @@ -16,16 +19,13 @@ public class RemovePinCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { try { m.setRegistrationLockPin(Optional.absent()); - return 0; } catch (UnauthenticatedResponseException e) { - System.err.println("Remove pin error: " + e.getMessage()); - return 2; + throw new UnexpectedErrorException("Remove pin failed with unauthenticated response: " + e.getMessage()); } catch (IOException e) { - System.err.println("Remove pin error: " + e.getMessage()); - return 3; + throw new IOErrorException("Remove pin error: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/SendCommand.java b/src/main/java/org/asamk/signal/commands/SendCommand.java index 1976fb60..23d74165 100644 --- a/src/main/java/org/asamk/signal/commands/SendCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendCommand.java @@ -6,6 +6,10 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.Signal; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.util.IOUtils; import org.asamk.signal.util.Util; @@ -19,7 +23,6 @@ import java.nio.charset.Charset; import java.util.List; import static org.asamk.signal.util.ErrorUtils.handleAssertionError; -import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException; public class SendCommand implements DbusCommand { @@ -42,7 +45,7 @@ public class SendCommand implements DbusCommand { } @Override - public int handleCommand(final Namespace ns, final Signal signal) { + public void handleCommand(final Namespace ns, final Signal signal) throws CommandException { final List recipients = ns.getList("recipient"); final var isEndSession = ns.getBoolean("endsession"); final var groupIdString = ns.getString("group"); @@ -50,32 +53,27 @@ public class SendCommand implements DbusCommand { final var noRecipients = recipients == null || recipients.isEmpty(); if ((noRecipients && isEndSession) || (noRecipients && groupIdString == null && !isNoteToSelf)) { - System.err.println("No recipients given"); - System.err.println("Aborting sending."); - return 1; + throw new UserErrorException("No recipients given"); } if (!noRecipients && groupIdString != null) { - System.err.println("You cannot specify recipients by phone number and groups at the same time"); - return 1; + throw new UserErrorException("You cannot specify recipients by phone number and groups at the same time"); } if (!noRecipients && isNoteToSelf) { - System.err.println("You cannot specify recipients by phone number and not to self at the same time"); - return 1; + throw new UserErrorException( + "You cannot specify recipients by phone number and not to self at the same time"); } if (isEndSession) { try { signal.sendEndSessionMessage(recipients); - return 0; + return; } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (Signal.Error.UntrustedIdentity e) { - System.err.println("Failed to send message: " + e.getMessage()); - return 4; + throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage()); } catch (DBusExecutionException e) { - System.err.println("Failed to send message: " + e.getMessage()); - return 2; + throw new UnexpectedErrorException("Failed to send message: " + e.getMessage()); } } @@ -84,9 +82,7 @@ public class SendCommand implements DbusCommand { try { messageText = IOUtils.readAll(System.in, Charset.defaultCharset()); } catch (IOException e) { - System.err.println("Failed to read message from stdin: " + e.getMessage()); - System.err.println("Aborting sending."); - return 1; + throw new UserErrorException("Failed to read message from stdin: " + e.getMessage()); } } @@ -102,23 +98,18 @@ public class SendCommand implements DbusCommand { try { groupId = Util.decodeGroupId(groupIdString).serialize(); } catch (GroupIdFormatException e) { - handleGroupIdFormatException(e); - return 1; + throw new UserErrorException("Invalid group id:" + e.getMessage()); } try { var timestamp = signal.sendGroupMessage(messageText, attachments, groupId); writer.println("{}", timestamp); - return 0; + return; } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (DBusExecutionException e) { - System.err.println("Failed to send group message: " + e.getMessage()); - return 2; - } catch (IOException e) { - e.printStackTrace(); - return 3; + throw new UnexpectedErrorException("Failed to send group message: " + e.getMessage()); } } @@ -126,41 +117,29 @@ public class SendCommand implements DbusCommand { try { var timestamp = signal.sendNoteToSelfMessage(messageText, attachments); writer.println("{}", timestamp); - return 0; + return; } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (Signal.Error.UntrustedIdentity e) { - System.err.println("Failed to send message: " + e.getMessage()); - return 4; + throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage()); } catch (DBusExecutionException e) { - System.err.println("Failed to send note to self message: " + e.getMessage()); - return 2; - } catch (IOException e) { - e.printStackTrace(); - return 3; + throw new UnexpectedErrorException("Failed to send note to self message: " + e.getMessage()); } } try { var timestamp = signal.sendMessage(messageText, attachments, recipients); writer.println("{}", timestamp); - return 0; } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (UnknownObject e) { - System.err.println("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage()); - return 1; + throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage()); } catch (Signal.Error.UntrustedIdentity e) { - System.err.println("Failed to send message: " + e.getMessage()); - return 4; + throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage()); } catch (DBusExecutionException e) { - System.err.println("Failed to send message: " + e.getMessage()); - return 2; - } catch (IOException e) { - e.printStackTrace(); - return 3; + throw new UnexpectedErrorException("Failed to send message: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/SendContactsCommand.java b/src/main/java/org/asamk/signal/commands/SendContactsCommand.java index f5eacf81..176f1bb9 100644 --- a/src/main/java/org/asamk/signal/commands/SendContactsCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendContactsCommand.java @@ -3,6 +3,9 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException; import org.asamk.signal.manager.Manager; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; @@ -16,16 +19,13 @@ public class SendContactsCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { try { m.sendContacts(); - return 0; } catch (UntrustedIdentityException e) { - System.err.println("SendContacts error: " + e.getMessage()); - return 2; + throw new UntrustedKeyErrorException("SendContacts error: " + e.getMessage()); } catch (IOException e) { - System.err.println("SendContacts error: " + e.getMessage()); - return 3; + throw new IOErrorException("SendContacts error: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java index bcae9d41..b9cbc047 100644 --- a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java @@ -5,7 +5,11 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; @@ -18,11 +22,6 @@ import java.io.IOException; import java.util.List; import static org.asamk.signal.util.ErrorUtils.handleAssertionError; -import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException; -import static org.asamk.signal.util.ErrorUtils.handleGroupNotFoundException; -import static org.asamk.signal.util.ErrorUtils.handleIOException; -import static org.asamk.signal.util.ErrorUtils.handleInvalidNumberException; -import static org.asamk.signal.util.ErrorUtils.handleNotAGroupMemberException; import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResults; public class SendReactionCommand implements LocalCommand { @@ -46,19 +45,16 @@ public class SendReactionCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { final List recipients = ns.getList("recipient"); final var groupIdString = ns.getString("group"); final var noRecipients = recipients == null || recipients.isEmpty(); if (noRecipients && groupIdString == null) { - System.err.println("No recipients given"); - System.err.println("Aborting sending."); - return 1; + throw new UserErrorException("No recipients given"); } if (!noRecipients && groupIdString != null) { - System.err.println("You cannot specify recipients by phone number and groups at the same time"); - return 1; + throw new UserErrorException("You cannot specify recipients by phone number and groups at the same time"); } final var emoji = ns.getString("emoji"); @@ -66,35 +62,37 @@ public class SendReactionCommand implements LocalCommand { final var targetAuthor = ns.getString("target_author"); final long targetTimestamp = ns.getLong("target_timestamp"); - try { - final var writer = new PlainTextWriterImpl(System.out); + final var writer = new PlainTextWriterImpl(System.out); + + final Pair> results; + + GroupId groupId = null; + if (groupId != null) { + try { + groupId = Util.decodeGroupId(groupIdString); + } catch (GroupIdFormatException e) { + throw new UserErrorException("Invalid group id:" + e.getMessage()); + } + } - final Pair> results; - if (groupIdString != null) { - var groupId = Util.decodeGroupId(groupIdString); + try { + if (groupId != null) { results = m.sendGroupMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, groupId); } else { results = m.sendMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, recipients); } - return handleTimestampAndSendMessageResults(writer, results.first(), results.second()); + handleTimestampAndSendMessageResults(writer, results.first(), results.second()); } catch (IOException e) { - handleIOException(e); - return 3; + throw new IOErrorException("Failed to send message: " + e.getMessage()); } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (GroupNotFoundException e) { - handleGroupNotFoundException(e); - return 1; + throw new UserErrorException("Failed to send to group: " + e.getMessage()); } catch (NotAGroupMemberException e) { - handleNotAGroupMemberException(e); - return 1; - } catch (GroupIdFormatException e) { - handleGroupIdFormatException(e); - return 1; + throw new UserErrorException("Failed to send to group: " + e.getMessage()); } catch (InvalidNumberException e) { - handleInvalidNumberException(e); - return 1; + throw new UserErrorException("Invalid number: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/SetPinCommand.java b/src/main/java/org/asamk/signal/commands/SetPinCommand.java index fff105be..56b4b8a4 100644 --- a/src/main/java/org/asamk/signal/commands/SetPinCommand.java +++ b/src/main/java/org/asamk/signal/commands/SetPinCommand.java @@ -3,6 +3,9 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; import org.asamk.signal.manager.Manager; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException; @@ -18,17 +21,14 @@ public class SetPinCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { try { var registrationLockPin = ns.getString("registrationLockPin"); m.setRegistrationLockPin(Optional.of(registrationLockPin)); - return 0; } catch (UnauthenticatedResponseException e) { - System.err.println("Set pin error: " + e.getMessage()); - return 2; + throw new UnexpectedErrorException("Set pin error failed with unauthenticated response: " + e.getMessage()); } catch (IOException e) { - System.err.println("Set pin error: " + e.getMessage()); - return 3; + throw new IOErrorException("Set pin error: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/TrustCommand.java b/src/main/java/org/asamk/signal/commands/TrustCommand.java index 277291eb..08fe6a41 100644 --- a/src/main/java/org/asamk/signal/commands/TrustCommand.java +++ b/src/main/java/org/asamk/signal/commands/TrustCommand.java @@ -4,8 +4,9 @@ import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; -import org.asamk.signal.util.ErrorUtils; import org.asamk.signal.util.Hex; import org.whispersystems.signalservice.api.util.InvalidNumberException; @@ -25,13 +26,12 @@ public class TrustCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { var number = ns.getString("number"); if (ns.getBoolean("trust_all_known_keys")) { var res = m.trustIdentityAllKeys(number); if (!res) { - System.err.println("Failed to set the trust for this number, make sure the number is correct."); - return 1; + throw new UserErrorException("Failed to set the trust for this number, make sure the number is correct."); } } else { var safetyNumber = ns.getString("verified_safety_number"); @@ -42,46 +42,38 @@ public class TrustCommand implements LocalCommand { try { fingerprintBytes = Hex.toByteArray(safetyNumber.toLowerCase(Locale.ROOT)); } catch (Exception e) { - System.err.println( + throw new UserErrorException( "Failed to parse the fingerprint, make sure the fingerprint is a correctly encoded hex string without additional characters."); - return 1; } boolean res; try { res = m.trustIdentityVerified(number, fingerprintBytes); } catch (InvalidNumberException e) { - ErrorUtils.handleInvalidNumberException(e); - return 1; + throw new UserErrorException("Failed to parse recipient: " + e.getMessage()); } if (!res) { - System.err.println( + throw new UserErrorException( "Failed to set the trust for the fingerprint of this number, make sure the number and the fingerprint are correct."); - return 1; } } else if (safetyNumber.length() == 60) { boolean res; try { res = m.trustIdentityVerifiedSafetyNumber(number, safetyNumber); } catch (InvalidNumberException e) { - ErrorUtils.handleInvalidNumberException(e); - return 1; + throw new UserErrorException("Failed to parse recipient: " + e.getMessage()); } if (!res) { - System.err.println( + throw new UserErrorException( "Failed to set the trust for the safety number of this phone number, make sure the phone number and the safety number are correct."); - return 1; } } else { - System.err.println( + throw new UserErrorException( "Safety number has invalid format, either specify the old hex fingerprint or the new safety number"); - return 1; } } else { - System.err.println( + throw new UserErrorException( "You need to specify the fingerprint/safety number you have verified with -v SAFETY_NUMBER"); - return 1; } } - return 0; } } diff --git a/src/main/java/org/asamk/signal/commands/UnblockCommand.java b/src/main/java/org/asamk/signal/commands/UnblockCommand.java index b9d6e849..6e067ee5 100644 --- a/src/main/java/org/asamk/signal/commands/UnblockCommand.java +++ b/src/main/java/org/asamk/signal/commands/UnblockCommand.java @@ -3,14 +3,19 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.util.InvalidNumberException; public class UnblockCommand implements LocalCommand { + private final static Logger logger = LoggerFactory.getLogger(UnblockCommand.class); + @Override public void attachToSubparser(final Subparser subparser) { subparser.addArgument("contact").help("Contact number").nargs("*"); @@ -19,12 +24,12 @@ public class UnblockCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { - for (var contact_number : ns.getList("contact")) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { + for (var contactNumber : ns.getList("contact")) { try { - m.setContactBlocked(contact_number, false); + m.setContactBlocked(contactNumber, false); } catch (InvalidNumberException e) { - System.err.println(e.getMessage()); + logger.warn("Invalid number: {}", contactNumber); } } @@ -33,12 +38,12 @@ public class UnblockCommand implements LocalCommand { try { var groupId = Util.decodeGroupId(groupIdString); m.setGroupBlocked(groupId, false); - } catch (GroupIdFormatException | GroupNotFoundException e) { - System.err.println(e.getMessage()); + } catch (GroupIdFormatException e) { + logger.warn("Invalid group id: {}", groupIdString); + } catch (GroupNotFoundException e) { + logger.warn("Unknown group id: {}", groupIdString); } } } - - return 0; } } diff --git a/src/main/java/org/asamk/signal/commands/UnregisterCommand.java b/src/main/java/org/asamk/signal/commands/UnregisterCommand.java index 079070e6..1846eba1 100644 --- a/src/main/java/org/asamk/signal/commands/UnregisterCommand.java +++ b/src/main/java/org/asamk/signal/commands/UnregisterCommand.java @@ -3,6 +3,8 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.manager.Manager; import java.io.IOException; @@ -15,13 +17,11 @@ public class UnregisterCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { try { m.unregister(); - return 0; } catch (IOException e) { - System.err.println("Unregister error: " + e.getMessage()); - return 3; + throw new IOErrorException("Unregister error: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java b/src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java index 8211e190..13723f09 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java @@ -3,6 +3,8 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.manager.Manager; import java.io.IOException; @@ -15,13 +17,11 @@ public class UpdateAccountCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { try { m.updateAccountAttributes(); - return 0; } catch (IOException e) { - System.err.println("UpdateAccount error: " + e.getMessage()); - return 3; + throw new IOErrorException("UpdateAccount error: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java b/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java index c2b994d6..c8ad613b 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java @@ -3,6 +3,9 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.whispersystems.signalservice.api.util.InvalidNumberException; @@ -22,7 +25,7 @@ public class UpdateContactCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { var number = ns.getString("number"); var name = ns.getString("name"); @@ -34,13 +37,9 @@ public class UpdateContactCommand implements LocalCommand { m.setExpirationTimer(number, expiration); } } catch (InvalidNumberException e) { - System.err.println("Invalid contact number: " + e.getMessage()); - return 1; + throw new UserErrorException("Invalid contact number: " + e.getMessage()); } catch (IOException e) { - System.err.println("Update contact error: " + e.getMessage()); - return 3; + throw new IOErrorException("Update contact error: " + e.getMessage()); } - - return 0; } } diff --git a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java index fdb23ea1..204dcfe2 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java @@ -5,19 +5,20 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.Signal; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.util.Util; import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; import java.util.ArrayList; import java.util.Base64; import java.util.List; import static org.asamk.signal.util.ErrorUtils.handleAssertionError; -import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException; public class UpdateGroupCommand implements DbusCommand { @@ -32,15 +33,14 @@ public class UpdateGroupCommand implements DbusCommand { } @Override - public int handleCommand(final Namespace ns, final Signal signal) { + public void handleCommand(final Namespace ns, final Signal signal) throws CommandException { final var writer = new PlainTextWriterImpl(System.out); byte[] groupId = null; if (ns.getString("group") != null) { try { groupId = Util.decodeGroupId(ns.getString("group")).serialize(); } catch (GroupIdFormatException e) { - handleGroupIdFormatException(e); - return 1; + throw new UserErrorException("Invalid group id:" + e.getMessage()); } } if (groupId == null) { @@ -65,23 +65,15 @@ public class UpdateGroupCommand implements DbusCommand { try { var newGroupId = signal.updateGroup(groupId, groupName, groupMembers, groupAvatar); if (groupId.length != newGroupId.length) { - try { - writer.println("Creating new group \"{}\" …", Base64.getEncoder().encodeToString(newGroupId)); - } catch (IOException e) { - e.printStackTrace(); - return 3; - } + writer.println("Created new group: \"{}\"", Base64.getEncoder().encodeToString(newGroupId)); } - return 0; } catch (AssertionError e) { handleAssertionError(e); - return 1; + throw e; } catch (Signal.Error.AttachmentInvalid e) { - System.err.println("Failed to add avatar attachment for group\": " + e.getMessage()); - return 1; + throw new UserErrorException("Failed to add avatar attachment for group\": " + e.getMessage()); } catch (DBusExecutionException e) { - System.err.println("Failed to send message: " + e.getMessage()); - return 2; + throw new UnexpectedErrorException("Failed to send message: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java b/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java index b8c7b08c..c3fc2e88 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java @@ -4,6 +4,8 @@ import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.manager.Manager; import org.whispersystems.libsignal.util.guava.Optional; @@ -26,23 +28,21 @@ public class UpdateProfileCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { var name = ns.getString("name"); var about = ns.getString("about"); var aboutEmoji = ns.getString("about_emoji"); var avatarPath = ns.getString("avatar"); boolean removeAvatar = ns.getBoolean("remove_avatar"); + Optional avatarFile = removeAvatar + ? Optional.absent() + : avatarPath == null ? null : Optional.of(new File(avatarPath)); + try { - Optional avatarFile = removeAvatar - ? Optional.absent() - : avatarPath == null ? null : Optional.of(new File(avatarPath)); m.setProfile(name, about, aboutEmoji, avatarFile); } catch (IOException e) { - System.err.println("Update profile error: " + e.getMessage()); - return 3; + throw new IOErrorException("Update profile error: " + e.getMessage()); } - - return 0; } } diff --git a/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java b/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java index 9d72a6c5..1ed14e21 100644 --- a/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java +++ b/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java @@ -4,6 +4,9 @@ import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.PlainTextWriterImpl; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.StickerPackInvalidException; import org.slf4j.Logger; @@ -23,19 +26,17 @@ public class UploadStickerPackCommand implements LocalCommand { } @Override - public int handleCommand(final Namespace ns, final Manager m) { + public void handleCommand(final Namespace ns, final Manager m) throws CommandException { final var writer = new PlainTextWriterImpl(System.out); + var path = new File(ns.getString("path")); + try { - var path = new File(ns.getString("path")); var url = m.uploadStickerPack(path); writer.println("{}", url); - return 0; } catch (IOException e) { - System.err.println("Upload error: " + e.getMessage()); - return 3; + throw new IOErrorException("Upload error: " + e.getMessage()); } catch (StickerPackInvalidException e) { - System.err.println("Invalid sticker pack: " + e.getMessage()); - return 1; + throw new UserErrorException("Invalid sticker pack: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/VerifyCommand.java b/src/main/java/org/asamk/signal/commands/VerifyCommand.java index a244581d..c26c1d3a 100644 --- a/src/main/java/org/asamk/signal/commands/VerifyCommand.java +++ b/src/main/java/org/asamk/signal/commands/VerifyCommand.java @@ -3,6 +3,10 @@ package org.asamk.signal.commands; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.RegistrationManager; import org.whispersystems.signalservice.api.KeyBackupServicePinException; import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException; @@ -19,26 +23,23 @@ public class VerifyCommand implements RegistrationCommand { } @Override - public int handleCommand(final Namespace ns, final RegistrationManager m) { + public void handleCommand(final Namespace ns, final RegistrationManager m) throws CommandException { + var verificationCode = ns.getString("verificationCode"); + var pin = ns.getString("pin"); + try { - var verificationCode = ns.getString("verificationCode"); - var pin = ns.getString("pin"); m.verifyAccount(verificationCode, pin); - return 0; } catch (LockedException e) { - System.err.println("Verification failed! This number is locked with a pin. Hours remaining until reset: " - + (e.getTimeRemaining() / 1000 / 60 / 60)); - System.err.println("Use '--pin PIN_CODE' to specify the registration lock PIN"); - return 1; + throw new UserErrorException( + "Verification failed! This number is locked with a pin. Hours remaining until reset: " + + (e.getTimeRemaining() / 1000 / 60 / 60) + + "\nUse '--pin PIN_CODE' to specify the registration lock PIN"); } catch (KeyBackupServicePinException e) { - System.err.println("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining()); - return 1; + throw new UserErrorException("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining()); } catch (KeyBackupSystemNoDataException e) { - System.err.println("Verification failed! No KBS data."); - return 3; + throw new UnexpectedErrorException("Verification failed! No KBS data."); } catch (IOException e) { - System.err.println("Verify error: " + e.getMessage()); - return 3; + throw new IOErrorException("Verify error: " + e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/commands/exceptions/CommandException.java b/src/main/java/org/asamk/signal/commands/exceptions/CommandException.java new file mode 100644 index 00000000..c82ef542 --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/exceptions/CommandException.java @@ -0,0 +1,8 @@ +package org.asamk.signal.commands.exceptions; + +public class CommandException extends Exception { + + public CommandException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/asamk/signal/commands/exceptions/IOErrorException.java b/src/main/java/org/asamk/signal/commands/exceptions/IOErrorException.java new file mode 100644 index 00000000..e405600c --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/exceptions/IOErrorException.java @@ -0,0 +1,8 @@ +package org.asamk.signal.commands.exceptions; + +public final class IOErrorException extends CommandException { + + public IOErrorException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/asamk/signal/commands/exceptions/UnexpectedErrorException.java b/src/main/java/org/asamk/signal/commands/exceptions/UnexpectedErrorException.java new file mode 100644 index 00000000..b6f231df --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/exceptions/UnexpectedErrorException.java @@ -0,0 +1,8 @@ +package org.asamk.signal.commands.exceptions; + +public final class UnexpectedErrorException extends CommandException { + + public UnexpectedErrorException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/asamk/signal/commands/exceptions/UntrustedKeyErrorException.java b/src/main/java/org/asamk/signal/commands/exceptions/UntrustedKeyErrorException.java new file mode 100644 index 00000000..c215f414 --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/exceptions/UntrustedKeyErrorException.java @@ -0,0 +1,8 @@ +package org.asamk.signal.commands.exceptions; + +public final class UntrustedKeyErrorException extends CommandException { + + public UntrustedKeyErrorException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/asamk/signal/commands/exceptions/UserErrorException.java b/src/main/java/org/asamk/signal/commands/exceptions/UserErrorException.java new file mode 100644 index 00000000..84e957cc --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/exceptions/UserErrorException.java @@ -0,0 +1,8 @@ +package org.asamk.signal.commands.exceptions; + +public final class UserErrorException extends CommandException { + + public UserErrorException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/asamk/signal/util/ErrorUtils.java b/src/main/java/org/asamk/signal/util/ErrorUtils.java index 149b16c0..595509a6 100644 --- a/src/main/java/org/asamk/signal/util/ErrorUtils.java +++ b/src/main/java/org/asamk/signal/util/ErrorUtils.java @@ -1,38 +1,34 @@ package org.asamk.signal.util; import org.asamk.signal.PlainTextWriter; -import org.asamk.signal.manager.groups.GroupIdFormatException; -import org.asamk.signal.manager.groups.GroupNotFoundException; -import org.asamk.signal.manager.groups.NotAGroupMemberException; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.IOErrorException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.messages.SendMessageResult; -import org.whispersystems.signalservice.api.util.InvalidNumberException; -import java.io.IOException; import java.util.ArrayList; import java.util.List; public class ErrorUtils { + private final static Logger logger = LoggerFactory.getLogger(ErrorUtils.class); + private ErrorUtils() { } public static void handleAssertionError(AssertionError e) { - System.err.println("Failed to send/receive message (Assertion): " + e.getMessage()); - e.printStackTrace(); - System.err.println( - "If you use an Oracle JRE please check if you have unlimited strength crypto enabled, see README"); + logger.warn("If you use an Oracle JRE please check if you have unlimited strength crypto enabled, see README"); } - public static int handleTimestampAndSendMessageResults( - PlainTextWriter writer, - long timestamp, - List results - ) throws IOException { + public static void handleTimestampAndSendMessageResults( + PlainTextWriter writer, long timestamp, List results + ) throws CommandException { if (timestamp != 0) { writer.println("{}", timestamp); } var errors = getErrorMessagesFromSendMessageResults(results); - return handleSendMessageResultErrors(errors); + handleSendMessageResultErrors(errors); } public static List getErrorMessagesFromSendMessageResults(List results) { @@ -58,39 +54,15 @@ public class ErrorUtils { return null; } - private static int handleSendMessageResultErrors(List errors) { + private static void handleSendMessageResultErrors(List errors) throws CommandException { if (errors.size() == 0) { - return 0; + return; } - System.err.println("Failed to send (some) messages:"); + var message = new StringBuilder(); + message.append("Failed to send (some) messages:\n"); for (var error : errors) { - System.err.println(error); + message.append(error).append("\n"); } - return 3; - } - - public static void handleIOException(IOException e) { - System.err.println("Failed to send message: " + e.getMessage()); - } - - public static void handleGroupNotFoundException(GroupNotFoundException e) { - System.err.println("Failed to send to group: " + e.getMessage()); - System.err.println("Aborting sending."); - } - - public static void handleNotAGroupMemberException(NotAGroupMemberException e) { - System.err.println("Failed to send to group: " + e.getMessage()); - System.err.println("Update the group on another device to readd the user to this group."); - System.err.println("Aborting sending."); - } - - public static void handleGroupIdFormatException(GroupIdFormatException e) { - System.err.println(e.getMessage()); - System.err.println("Aborting sending."); - } - - public static void handleInvalidNumberException(InvalidNumberException e) { - System.err.println("Failed to parse recipient: " + e.getMessage()); - System.err.println("Aborting sending."); + throw new IOErrorException(message.toString()); } } -- 2.51.0 From 8249f852f9244cc83698c9330a304604f385daaa Mon Sep 17 00:00:00 2001 From: AsamK Date: Tue, 23 Feb 2021 21:50:31 +0100 Subject: [PATCH 08/16] Fix issue with broken sessions Fixes #530 --- .../storage/protocol/JsonSessionStore.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSessionStore.java index 94d2d681..1b5384a4 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSessionStore.java @@ -12,6 +12,7 @@ import org.asamk.signal.manager.util.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.SignalProtocolAddress; +import org.whispersystems.libsignal.protocol.CiphertextMessage; import org.whispersystems.libsignal.state.SessionRecord; import org.whispersystems.signalservice.api.SignalServiceSessionStore; import org.whispersystems.signalservice.api.push.SignalServiceAddress; @@ -55,9 +56,7 @@ class JsonSessionStore implements SignalServiceSessionStore { return new SessionRecord(info.sessionRecord); } catch (IOException e) { logger.warn("Failed to load session, resetting session: {}", e.getMessage()); - final var sessionRecord = new SessionRecord(); - info.sessionRecord = sessionRecord.serialize(); - return sessionRecord; + return new SessionRecord(); } } } @@ -104,7 +103,16 @@ class JsonSessionStore implements SignalServiceSessionStore { var serviceAddress = resolveSignalServiceAddress(address.getName()); for (var info : sessions) { if (info.address.matches(serviceAddress) && info.deviceId == address.getDeviceId()) { - return true; + final SessionRecord sessionRecord; + try { + sessionRecord = new SessionRecord(info.sessionRecord); + } catch (IOException e) { + logger.warn("Failed to check session: {}", e.getMessage()); + return false; + } + + return sessionRecord.hasSenderChain() + && sessionRecord.getSessionVersion() == CiphertextMessage.CURRENT_VERSION; } } return false; -- 2.51.0 From 4860caef63080c501e06418f1bca7030a7c7898d Mon Sep 17 00:00:00 2001 From: AsamK Date: Thu, 25 Feb 2021 19:20:02 +0100 Subject: [PATCH 09/16] Improve behavior of trust command - Remove all other identities for the same number Fixes #540 --- .../org/asamk/signal/manager/Manager.java | 104 ++++++++++-------- .../storage/protocol/IdentityInfo.java | 7 -- .../protocol/JsonIdentityKeyStore.java | 8 ++ .../protocol/JsonSignalProtocolStore.java | 4 + 4 files changed, 69 insertions(+), 54 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index caedf2f1..88335916 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -156,6 +156,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.Function; import java.util.stream.Collectors; import static org.asamk.signal.manager.config.ServiceConfig.capabilities; @@ -1211,10 +1212,12 @@ public class Manager implements Closeable { try { messageSender.sendMessage(message, unidentifiedAccessHelper.getAccessForSync()); } catch (UntrustedIdentityException e) { - account.getSignalProtocolStore() - .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), - e.getIdentityKey(), - TrustLevel.UNTRUSTED); + if (e.getIdentityKey() != null) { + account.getSignalProtocolStore() + .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), + e.getIdentityKey(), + TrustLevel.UNTRUSTED); + } throw e; } } @@ -1296,10 +1299,12 @@ public class Manager implements Closeable { } return new Pair<>(timestamp, result); } catch (UntrustedIdentityException e) { - account.getSignalProtocolStore() - .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), - e.getIdentityKey(), - TrustLevel.UNTRUSTED); + if (e.getIdentityKey() != null) { + account.getSignalProtocolStore() + .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), + e.getIdentityKey(), + TrustLevel.UNTRUSTED); + } return new Pair<>(timestamp, List.of()); } } else { @@ -1369,10 +1374,12 @@ public class Manager implements Closeable { false, System.currentTimeMillis() - startTime); } catch (UntrustedIdentityException e) { - account.getSignalProtocolStore() - .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), - e.getIdentityKey(), - TrustLevel.UNTRUSTED); + if (e.getIdentityKey() != null) { + account.getSignalProtocolStore() + .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), + e.getIdentityKey(), + TrustLevel.UNTRUSTED); + } return SendMessageResult.identityFailure(recipient, e.getIdentityKey()); } } @@ -1385,10 +1392,12 @@ public class Manager implements Closeable { try { return messageSender.sendMessage(address, unidentifiedAccessHelper.getAccessFor(address), message); } catch (UntrustedIdentityException e) { - account.getSignalProtocolStore() - .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), - e.getIdentityKey(), - TrustLevel.UNTRUSTED); + if (e.getIdentityKey() != null) { + account.getSignalProtocolStore() + .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), + e.getIdentityKey(), + TrustLevel.UNTRUSTED); + } return SendMessageResult.identityFailure(address, e.getIdentityKey()); } } @@ -2388,26 +2397,7 @@ public class Manager implements Closeable { */ public boolean trustIdentityVerified(String name, byte[] fingerprint) throws InvalidNumberException { var address = canonicalizeAndResolveSignalServiceAddress(name); - var ids = account.getSignalProtocolStore().getIdentities(address); - if (ids == null) { - return false; - } - for (var id : ids) { - if (!Arrays.equals(id.getIdentityKey().serialize(), fingerprint)) { - continue; - } - - account.getSignalProtocolStore() - .setIdentityTrustLevel(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); - try { - sendVerifiedMessage(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); - } catch (IOException | UntrustedIdentityException e) { - logger.warn("Failed to send verification sync message: {}", e.getMessage()); - } - account.save(); - return true; - } - return false; + return trustIdentity(address, (identityKey) -> Arrays.equals(identityKey.serialize(), fingerprint)); } /** @@ -2418,26 +2408,46 @@ public class Manager implements Closeable { */ public boolean trustIdentityVerifiedSafetyNumber(String name, String safetyNumber) throws InvalidNumberException { var address = canonicalizeAndResolveSignalServiceAddress(name); + return trustIdentity(address, (identityKey) -> safetyNumber.equals(computeSafetyNumber(address, identityKey))); + } + + private boolean trustIdentity(SignalServiceAddress address, Function verifier) { var ids = account.getSignalProtocolStore().getIdentities(address); if (ids == null) { return false; } + + IdentityInfo foundIdentity = null; + for (var id : ids) { - if (!safetyNumber.equals(computeSafetyNumber(address, id.getIdentityKey()))) { - continue; + if (verifier.apply(id.getIdentityKey())) { + foundIdentity = id; + break; } + } - account.getSignalProtocolStore() - .setIdentityTrustLevel(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); - try { - sendVerifiedMessage(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); - } catch (IOException | UntrustedIdentityException e) { - logger.warn("Failed to send verification sync message: {}", e.getMessage()); + if (foundIdentity == null) { + return false; + } + + account.getSignalProtocolStore() + .setIdentityTrustLevel(address, foundIdentity.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); + try { + sendVerifiedMessage(address, foundIdentity.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); + } catch (IOException | UntrustedIdentityException e) { + logger.warn("Failed to send verification sync message: {}", e.getMessage()); + } + + // Successfully trusted the new identity, now remove all other identities for that number + for (var id : ids) { + if (id == foundIdentity) { + continue; } - account.save(); - return true; + account.getSignalProtocolStore().removeIdentity(address, id.getIdentityKey()); } - return false; + + account.save(); + return true; } /** diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/IdentityInfo.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/IdentityInfo.java index d4af11f2..652bf524 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/IdentityInfo.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/IdentityInfo.java @@ -13,13 +13,6 @@ public class IdentityInfo { TrustLevel trustLevel; Date added; - public IdentityInfo(SignalServiceAddress address, IdentityKey identityKey, TrustLevel trustLevel) { - this.address = address; - this.identityKey = identityKey; - this.trustLevel = trustLevel; - this.added = new Date(); - } - IdentityInfo(SignalServiceAddress address, IdentityKey identityKey, TrustLevel trustLevel, Date added) { this.address = address; this.identityKey = identityKey; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java index ed04e556..561138c6 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java @@ -125,6 +125,10 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { identities.add(new IdentityInfo(serviceAddress, identityKey, trustLevel, new Date())); } + public void removeIdentity(SignalServiceAddress serviceAddress, IdentityKey identityKey) { + identities.removeIf(id -> id.address.matches(serviceAddress) && id.identityKey.equals(identityKey)); + } + @Override public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) { // TODO implement possibility for different handling of incoming/outgoing trust decisions @@ -143,6 +147,10 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { } } + if (!trustOnFirstUse) { + saveIdentity(resolveSignalServiceAddress(address.getName()), identityKey, TrustLevel.UNTRUSTED, null); + } + return trustOnFirstUse; } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignalProtocolStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignalProtocolStore.java index 5a863b6e..d47f7a1a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignalProtocolStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignalProtocolStore.java @@ -91,6 +91,10 @@ public class JsonSignalProtocolStore implements SignalServiceProtocolStore { identityKeyStore.setIdentityTrustLevel(serviceAddress, identityKey, trustLevel); } + public void removeIdentity(SignalServiceAddress serviceAddress, IdentityKey identityKey) { + identityKeyStore.removeIdentity(serviceAddress, identityKey); + } + public List getIdentities() { return identityKeyStore.getIdentities(); } -- 2.51.0 From ef2ba0b8e0f7e9bf3ccebf18a5ddf35f3c7d03c3 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 27 Feb 2021 10:30:38 +0100 Subject: [PATCH 10/16] Create FUNDING.yml --- FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 FUNDING.yml diff --git a/FUNDING.yml b/FUNDING.yml new file mode 100644 index 00000000..d109a964 --- /dev/null +++ b/FUNDING.yml @@ -0,0 +1 @@ +liberapay: asamk -- 2.51.0 From 17d6b256e86223f356d6d73916bc0798c9c52214 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 27 Feb 2021 10:42:56 +0100 Subject: [PATCH 11/16] Create CONTRIBUTING.md --- CONTRIBUTING.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..0bc3167a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,8 @@ +# Question +If you have a question you can ask it in the [GitHub discussions page](https://github.com/AsamK/signal-cli/discussions) + +# Report a bug +- Search [existing issues](https://github.com/AsamK/signal-cli/issues?q=is%3Aissue) if it has been reported already +- If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/AsamK/signal-cli/issues/new). + - Be sure to include a **title and clear description**, as much relevant information as possible. + - Run the failing command with `--verbose` flag to get a more detailed log output and include that in the bug report -- 2.51.0 From 86711b0e5c37c7d202151c7d05b00e5bdeb7836b Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 27 Feb 2021 17:43:19 +0100 Subject: [PATCH 12/16] Print exception name when failing to load state fiel --- src/main/java/org/asamk/signal/App.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index 5b2c91c6..75ac5280 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -181,7 +181,11 @@ public class App { try { manager = RegistrationManager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT); } catch (Throwable e) { - throw new UnexpectedErrorException("Error loading or creating state file: " + e.getMessage()); + throw new UnexpectedErrorException("Error loading or creating state file: " + + e.getMessage() + + " (" + + e.getClass().getSimpleName() + + ")"); } try (var m = manager) { command.handleCommand(ns, m); @@ -234,7 +238,13 @@ public class App { } catch (NotRegisteredException e) { throw new UserErrorException("User " + username + " is not registered."); } catch (Throwable e) { - throw new UnexpectedErrorException("Error loading state file for user " + username + ": " + e.getMessage()); + throw new UnexpectedErrorException("Error loading state file for user " + + username + + ": " + + e.getMessage() + + " (" + + e.getClass().getSimpleName() + + ")"); } try { -- 2.51.0 From 9ca89b3dfaf4f25b0c3d1b831abe7d190c623634 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 28 Feb 2021 09:49:02 +0100 Subject: [PATCH 13/16] Catch all exceptions when loading cached message --- .../signal/manager/storage/messageCache/CachedMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java index 8ea723cc..404153b3 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java @@ -22,7 +22,7 @@ public final class CachedMessage { public SignalServiceEnvelope loadEnvelope() { try { return MessageCacheUtils.loadEnvelope(file); - } catch (IOException e) { + } catch (Exception e) { logger.error("Failed to load cached message envelope “{}”: {}", file, e.getMessage()); return null; } -- 2.51.0 From 8d0de675302fa4f3e0ea953cbb473c7a018e2bae Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 28 Feb 2021 10:19:40 +0100 Subject: [PATCH 14/16] Add getDisplayName to SignalProfile --- lib/src/main/java/org/asamk/signal/manager/Manager.java | 2 +- .../java/org/asamk/signal/manager/helper/GroupHelper.java | 2 +- .../asamk/signal/manager/storage/profiles/SignalProfile.java | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index 88335916..d34f4e08 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -2365,7 +2365,7 @@ public class Manager implements Closeable { final var profileEntry = account.getProfileStore().getProfileEntry(address); if (profileEntry != null && profileEntry.getProfile() != null) { - return profileEntry.getProfile().getName(); + return profileEntry.getProfile().getDisplayName(); } return null; diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java index 2efc18ad..c76075be 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -183,7 +183,7 @@ public class GroupHelper { .collect(Collectors.toSet()); if (noGv2Capability.size() > 0) { logger.warn("Cannot create a V2 group as some members don't support Groups V2: {}", - noGv2Capability.stream().map(SignalProfile::getName).collect(Collectors.joining(", "))); + noGv2Capability.stream().map(SignalProfile::getDisplayName).collect(Collectors.joining(", "))); return false; } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java index 6a761c29..9e5add98 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java @@ -75,6 +75,11 @@ public class SignalProfile { return name; } + public String getDisplayName() { + // First name and last name (if set) are separated by a NULL char + return name == null ? null : name.replace("\0", " "); + } + public String getAbout() { return about; } -- 2.51.0 From 1d2c7a479d791dedde6c2022ac65e9c82400af79 Mon Sep 17 00:00:00 2001 From: Adimarantis <74186638+bublath@users.noreply.github.com> Date: Mon, 1 Mar 2021 20:31:17 +0100 Subject: [PATCH 15/16] Dbus enhancements (#543) * Dbus enhancements * reverted sendMessage, completed isContactBlocked, fixed formatting * Updates based on feedback and fixes * Added trim * fixed getContactName Exception handling --- .../org/asamk/signal/manager/Manager.java | 2 +- .../storage/profiles/SignalProfile.java | 4 +- src/main/java/org/asamk/Signal.java | 16 ++ .../org/asamk/signal/dbus/DbusSignalImpl.java | 152 +++++++++++++++--- 4 files changed, 146 insertions(+), 28 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index d34f4e08..d8a1f563 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -529,7 +529,7 @@ public class Manager implements Closeable { ServiceConfig.AUTOMATIC_NETWORK_RETRY); } - private SignalProfile getRecipientProfile( + public SignalProfile getRecipientProfile( SignalServiceAddress address ) { return getRecipientProfile(address, false); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java index 9e5add98..d55e7e6c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java @@ -76,8 +76,8 @@ public class SignalProfile { } public String getDisplayName() { - // First name and last name (if set) are separated by a NULL char - return name == null ? null : name.replace("\0", " "); + // First name and last name (if set) are separated by a NULL char + trim space in case only one is filled + return name == null ? null : name.replace("\0", " ").trim(); } public String getAbout() { diff --git a/src/main/java/org/asamk/Signal.java b/src/main/java/org/asamk/Signal.java index 3bd1c0d7..9e81c788 100644 --- a/src/main/java/org/asamk/Signal.java +++ b/src/main/java/org/asamk/Signal.java @@ -54,6 +54,22 @@ public interface Signal extends DBusInterface { void updateProfile( String name, String about, String aboutEmoji, String avatarPath, boolean removeAvatar ) throws Error.Failure; + + public String version(); + + public List listNumbers(); + + public List getContactNumber(final String name) throws Error.Failure; + + public void quitGroup(final byte[] groupId) throws Error.GroupNotFound,Error.Failure; + + public boolean isContactBlocked(final String number); + + public boolean isGroupBlocked(final byte[] groupId); + + public boolean isMember(final byte[] groupId); + + public void joinGroup(final String groupLink) throws Error.Failure; class MessageReceived extends DBusSignal { diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 8cbbbc03..53ba5300 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -6,17 +6,24 @@ import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; +import org.asamk.signal.manager.groups.GroupInviteLinkUrl; +import org.asamk.signal.manager.storage.protocol.IdentityInfo; import org.asamk.signal.util.ErrorUtils; +import org.asamk.signal.manager.util.Utils; +import org.asamk.signal.BaseConfig; import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.InvalidNumberException; +import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; import java.util.stream.Collectors; public class DbusSignalImpl implements Signal { @@ -60,9 +67,8 @@ public class DbusSignalImpl implements Signal { } } - private static void checkSendMessageResults( - long timestamp, List results - ) throws DBusExecutionException { + private static void checkSendMessageResults(long timestamp, List results) + throws DBusExecutionException { if (results.size() == 1) { checkSendMessageResult(timestamp, results.get(0)); return; @@ -99,9 +105,8 @@ public class DbusSignalImpl implements Signal { } @Override - public long sendNoteToSelfMessage( - final String message, final List attachments - ) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { + public long sendNoteToSelfMessage(final String message, final List attachments) + throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { try { final var results = m.sendSelfMessage(message, attachments); checkSendMessageResult(results.first(), results.second()); @@ -140,13 +145,17 @@ public class DbusSignalImpl implements Signal { } } + // Since contact names might be empty if not defined, also potentially return + // the profile name @Override public String getContactName(final String number) { + String name=""; try { - return m.getContactName(number); - } catch (InvalidNumberException e) { + name = m.getContactOrProfileName(number); + } catch (Exception e) { throw new Error.InvalidNumber(e.getMessage()); } + return name; } @Override @@ -202,11 +211,8 @@ public class DbusSignalImpl implements Signal { if (group == null) { return List.of(); } else { - return group.getMembers() - .stream() - .map(m::resolveSignalServiceAddress) - .map(SignalServiceAddress::getLegacyIdentifier) - .collect(Collectors.toList()); + return group.getMembers().stream().map(m::resolveSignalServiceAddress) + .map(SignalServiceAddress::getLegacyIdentifier).collect(Collectors.toList()); } } @@ -225,9 +231,7 @@ public class DbusSignalImpl implements Signal { if (avatar.isEmpty()) { avatar = null; } - final var results = m.updateGroup(groupId == null ? null : GroupId.unknownVersion(groupId), - name, - members, + final var results = m.updateGroup(groupId == null ? null : GroupId.unknownVersion(groupId), name, members, avatar == null ? null : new File(avatar)); checkSendMessageResults(0, results.second()); return results.first().serialize(); @@ -248,19 +252,13 @@ public class DbusSignalImpl implements Signal { } @Override - public void updateProfile( - final String name, - final String about, - final String aboutEmoji, - String avatarPath, - final boolean removeAvatar - ) { + public void updateProfile(final String name, final String about, final String aboutEmoji, String avatarPath, + final boolean removeAvatar) { try { if (avatarPath.isEmpty()) { avatarPath = null; } - Optional avatarFile = removeAvatar - ? Optional.absent() + Optional avatarFile = removeAvatar ? Optional.absent() : avatarPath == null ? null : Optional.of(new File(avatarPath)); m.setProfile(name, about, aboutEmoji, avatarFile); } catch (IOException e) { @@ -268,4 +266,108 @@ public class DbusSignalImpl implements Signal { } } + // Provide option to query a version string in order to react on potential + // future interface changes + @Override + public String version() { + return BaseConfig.PROJECT_VERSION; + } + + // Create a unique list of Numbers from Identities and Contacts to really get + // all numbers the system knows + @Override + public List listNumbers() { + return Stream.concat(m.getIdentities().stream().map(i -> i.getAddress().getNumber().orNull()), + m.getContacts().stream().map(c -> c.number)) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + } + + @Override + public List getContactNumber(final String name) { + // Contact names have precendence. + List numbers=new ArrayList<>(); + var contacts = m.getContacts(); + for (var c : contacts) { + if (c.name!=null && c.name.equals(name)) { + numbers.add(c.number); + } + } + // Try profiles if no contact name was found + for (IdentityInfo identity : m.getIdentities()) { + String number = identity.getAddress().getNumber().orNull(); + if (number != null) { + var address = Utils.getSignalServiceAddressFromIdentifier(number); + var profile = m.getRecipientProfile(address); + String profileName = profile.getDisplayName(); + if (profileName.equals(name)) { + numbers.add(number); + } + } + } + if (numbers.size()==0) { + throw new Error.Failure("Contact name not found"); + } + return numbers; + } + + @Override + public void quitGroup(final byte[] groupId) { + var group = GroupId.unknownVersion(groupId); + try { + m.sendQuitGroupMessage(group); + } catch (GroupNotFoundException | NotAGroupMemberException e) { + throw new Error.GroupNotFound(e.getMessage()); + } catch (IOException e) { + throw new Error.Failure(e.getMessage()); + } + } + + @Override + public void joinGroup(final String groupLink) { + final GroupInviteLinkUrl linkUrl; + try { + linkUrl = GroupInviteLinkUrl.fromUri(groupLink); + m.joinGroup(linkUrl); + } catch (GroupInviteLinkUrl.InvalidGroupLinkException | GroupLinkNotActiveException e) { + throw new Error.Failure("Group link is invalid: " + e.getMessage()); + } catch (GroupInviteLinkUrl.UnknownGroupLinkVersionException e) { + throw new Error.Failure("Group link was created with an incompatible version: " + e.getMessage()); + } catch (IOException e) { + throw new Error.Failure(e.getMessage()); + } + } + + @Override + public boolean isContactBlocked(final String number) { + var contacts = m.getContacts(); + for (var c : contacts) { + if (c.number.equals(number)) { + return c.blocked; + } + } + return false; + } + + @Override + public boolean isGroupBlocked(final byte[] groupId) { + var group = m.getGroup(GroupId.unknownVersion(groupId)); + if (group == null) { + return false; + } else { + return group.isBlocked(); + } + } + + @Override + public boolean isMember(final byte[] groupId) { + var group = m.getGroup(GroupId.unknownVersion(groupId)); + if (group == null) { + return false; + } else { + return group.isMember(m.getSelfAddress()); + } + } + } -- 2.51.0 From 631f10c916652bf3fc521b2f799e8311282462b1 Mon Sep 17 00:00:00 2001 From: AsamK Date: Mon, 1 Mar 2021 20:33:12 +0100 Subject: [PATCH 16/16] Reformat --- src/main/java/org/asamk/Signal.java | 32 +++++------ .../org/asamk/signal/dbus/DbusSignalImpl.java | 53 ++++++++++++------- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/asamk/Signal.java b/src/main/java/org/asamk/Signal.java index 9e81c788..3c65deb0 100644 --- a/src/main/java/org/asamk/Signal.java +++ b/src/main/java/org/asamk/Signal.java @@ -54,22 +54,22 @@ public interface Signal extends DBusInterface { void updateProfile( String name, String about, String aboutEmoji, String avatarPath, boolean removeAvatar ) throws Error.Failure; - - public String version(); - - public List listNumbers(); - - public List getContactNumber(final String name) throws Error.Failure; - - public void quitGroup(final byte[] groupId) throws Error.GroupNotFound,Error.Failure; - - public boolean isContactBlocked(final String number); - - public boolean isGroupBlocked(final byte[] groupId); - - public boolean isMember(final byte[] groupId); - - public void joinGroup(final String groupLink) throws Error.Failure; + + public String version(); + + public List listNumbers(); + + public List getContactNumber(final String name) throws Error.Failure; + + public void quitGroup(final byte[] groupId) throws Error.GroupNotFound, Error.Failure; + + public boolean isContactBlocked(final String number); + + public boolean isGroupBlocked(final byte[] groupId); + + public boolean isMember(final byte[] groupId); + + public void joinGroup(final String groupLink) throws Error.Failure; class MessageReceived extends DBusSignal { diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 53ba5300..552c80ea 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -1,30 +1,30 @@ package org.asamk.signal.dbus; import org.asamk.Signal; +import org.asamk.signal.BaseConfig; import org.asamk.signal.manager.AttachmentInvalidException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupId; +import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; -import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.asamk.signal.manager.storage.protocol.IdentityInfo; -import org.asamk.signal.util.ErrorUtils; import org.asamk.signal.manager.util.Utils; -import org.asamk.signal.BaseConfig; +import org.asamk.signal.util.ErrorUtils; import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.whispersystems.libsignal.util.guava.Optional; +import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.InvalidNumberException; -import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.stream.Stream; import java.util.stream.Collectors; +import java.util.stream.Stream; public class DbusSignalImpl implements Signal { @@ -67,8 +67,9 @@ public class DbusSignalImpl implements Signal { } } - private static void checkSendMessageResults(long timestamp, List results) - throws DBusExecutionException { + private static void checkSendMessageResults( + long timestamp, List results + ) throws DBusExecutionException { if (results.size() == 1) { checkSendMessageResult(timestamp, results.get(0)); return; @@ -105,8 +106,9 @@ public class DbusSignalImpl implements Signal { } @Override - public long sendNoteToSelfMessage(final String message, final List attachments) - throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { + public long sendNoteToSelfMessage( + final String message, final List attachments + ) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { try { final var results = m.sendSelfMessage(message, attachments); checkSendMessageResult(results.first(), results.second()); @@ -149,7 +151,7 @@ public class DbusSignalImpl implements Signal { // the profile name @Override public String getContactName(final String number) { - String name=""; + String name = ""; try { name = m.getContactOrProfileName(number); } catch (Exception e) { @@ -211,8 +213,11 @@ public class DbusSignalImpl implements Signal { if (group == null) { return List.of(); } else { - return group.getMembers().stream().map(m::resolveSignalServiceAddress) - .map(SignalServiceAddress::getLegacyIdentifier).collect(Collectors.toList()); + return group.getMembers() + .stream() + .map(m::resolveSignalServiceAddress) + .map(SignalServiceAddress::getLegacyIdentifier) + .collect(Collectors.toList()); } } @@ -231,7 +236,9 @@ public class DbusSignalImpl implements Signal { if (avatar.isEmpty()) { avatar = null; } - final var results = m.updateGroup(groupId == null ? null : GroupId.unknownVersion(groupId), name, members, + final var results = m.updateGroup(groupId == null ? null : GroupId.unknownVersion(groupId), + name, + members, avatar == null ? null : new File(avatar)); checkSendMessageResults(0, results.second()); return results.first().serialize(); @@ -252,13 +259,19 @@ public class DbusSignalImpl implements Signal { } @Override - public void updateProfile(final String name, final String about, final String aboutEmoji, String avatarPath, - final boolean removeAvatar) { + public void updateProfile( + final String name, + final String about, + final String aboutEmoji, + String avatarPath, + final boolean removeAvatar + ) { try { if (avatarPath.isEmpty()) { avatarPath = null; } - Optional avatarFile = removeAvatar ? Optional.absent() + Optional avatarFile = removeAvatar + ? Optional.absent() : avatarPath == null ? null : Optional.of(new File(avatarPath)); m.setProfile(name, about, aboutEmoji, avatarFile); } catch (IOException e) { @@ -277,7 +290,7 @@ public class DbusSignalImpl implements Signal { // all numbers the system knows @Override public List listNumbers() { - return Stream.concat(m.getIdentities().stream().map(i -> i.getAddress().getNumber().orNull()), + return Stream.concat(m.getIdentities().stream().map(i -> i.getAddress().getNumber().orNull()), m.getContacts().stream().map(c -> c.number)) .filter(Objects::nonNull) .distinct() @@ -287,10 +300,10 @@ public class DbusSignalImpl implements Signal { @Override public List getContactNumber(final String name) { // Contact names have precendence. - List numbers=new ArrayList<>(); + List numbers = new ArrayList<>(); var contacts = m.getContacts(); for (var c : contacts) { - if (c.name!=null && c.name.equals(name)) { + if (c.name != null && c.name.equals(name)) { numbers.add(c.number); } } @@ -306,7 +319,7 @@ public class DbusSignalImpl implements Signal { } } } - if (numbers.size()==0) { + if (numbers.size() == 0) { throw new Error.Failure("Contact name not found"); } return numbers; -- 2.51.0