X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/f095d947f892830e1ced4af450df77a8f7ae6d5d..293c176831d9acc4b44c30e2fa13119152d08d3a:/src/main/java/org/asamk/signal/Main.java diff --git a/src/main/java/org/asamk/signal/Main.java b/src/main/java/org/asamk/signal/Main.java index 25807a6b..d70b00cb 100644 --- a/src/main/java/org/asamk/signal/Main.java +++ b/src/main/java/org/asamk/signal/Main.java @@ -28,10 +28,7 @@ import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.*; -import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo; -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.*; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions; import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException; @@ -46,10 +43,9 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; import java.security.Security; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; import java.util.concurrent.TimeoutException; public class Main { @@ -57,6 +53,8 @@ public class Main { public static final String SIGNAL_BUSNAME = "org.asamk.Signal"; public static final String SIGNAL_OBJECTPATH = "/org/asamk/Signal"; + private static final TimeZone tzUTC = TimeZone.getTimeZone("UTC"); + public static void main(String[] args) { // Workaround for BKS truststore Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(), 1); @@ -310,6 +308,9 @@ public class Main { } catch (GroupNotFoundException e) { handleGroupNotFoundException(e); return 1; + } catch (NotAGroupMemberException e) { + handleNotAGroupMemberException(e); + return 1; } catch (AttachmentInvalidException e) { System.err.println("Failed to add attachment: " + e.getMessage()); System.err.println("Aborting sending."); @@ -327,8 +328,8 @@ public class Main { dBusConn.addSigHandler(Signal.MessageReceived.class, new DBusSigHandler() { @Override public void handle(Signal.MessageReceived s) { - System.out.print(String.format("Envelope from: %s\nTimestamp: %d\nBody: %s\n", - s.getSender(), s.getTimestamp(), s.getMessage())); + System.out.print(String.format("Envelope from: %s\nTimestamp: %s\nBody: %s\n", + s.getSender(), formatTimestamp(s.getTimestamp()), s.getMessage())); if (s.getGroupId().length > 0) { System.out.println("Group info:"); System.out.println(" Id: " + Base64.encodeBytes(s.getGroupId())); @@ -401,6 +402,9 @@ public class Main { } catch (GroupNotFoundException e) { handleGroupNotFoundException(e); return 1; + } catch (NotAGroupMemberException e) { + handleNotAGroupMemberException(e); + return 1; } break; @@ -433,6 +437,9 @@ public class Main { } catch (GroupNotFoundException e) { handleGroupNotFoundException(e); return 1; + } catch (NotAGroupMemberException e) { + handleNotAGroupMemberException(e); + return 1; } catch (EncapsulatedExceptions e) { handleEncapsulatedExceptions(e); return 3; @@ -553,6 +560,13 @@ public class Main { System.err.println("Aborting sending."); } + private 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."); + } + + private static void handleDBusExecutionException(DBusExecutionException e) { System.err.println("Cannot connect to dbus: " + e.getMessage()); System.err.println("Aborting."); @@ -752,18 +766,28 @@ public class Main { } @Override - public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content) { + public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) { SignalServiceAddress source = envelope.getSourceAddress(); ContactInfo sourceContact = m.getContact(source.getNumber()); System.out.println(String.format("Envelope from: %s (device: %d)", (sourceContact == null ? "" : "“" + sourceContact.name + "” ") + source.getNumber(), envelope.getSourceDevice())); if (source.getRelay().isPresent()) { System.out.println("Relayed by: " + source.getRelay().get()); } - System.out.println("Timestamp: " + envelope.getTimestamp()); + System.out.println("Timestamp: " + formatTimestamp(envelope.getTimestamp())); if (envelope.isReceipt()) { System.out.println("Got receipt."); } else if (envelope.isSignalMessage() | envelope.isPreKeySignalMessage()) { + if (exception != null) { + if (exception instanceof org.whispersystems.libsignal.UntrustedIdentityException) { + org.whispersystems.libsignal.UntrustedIdentityException e = (org.whispersystems.libsignal.UntrustedIdentityException) exception; + System.out.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"); + } else { + System.out.println("Exception: " + exception.getMessage() + " (" + exception.getClass().getSimpleName() + ")"); + } + } if (content == null) { System.out.println("Failed to decrypt message."); } else { @@ -787,7 +811,7 @@ public class Main { System.out.println("Received sync read messages list"); for (ReadMessage rm : syncMessage.getRead().get()) { ContactInfo fromContact = m.getContact(rm.getSender()); - System.out.println("From: " + (fromContact == null ? "" : "“" + fromContact.name + "” ") + rm.getSender() + " Message timestamp: " + rm.getTimestamp()); + System.out.println("From: " + (fromContact == null ? "" : "“" + fromContact.name + "” ") + rm.getSender() + " Message timestamp: " + formatTimestamp(rm.getTimestamp())); } } if (syncMessage.getRequest().isPresent()) { @@ -810,10 +834,21 @@ public class Main { } else { to = "Unknown"; } - System.out.println("To: " + to + " , Message timestamp: " + sentTranscriptMessage.getTimestamp()); + System.out.println("To: " + to + " , Message timestamp: " + formatTimestamp(sentTranscriptMessage.getTimestamp())); + if (sentTranscriptMessage.getExpirationStartTimestamp() > 0) { + System.out.println("Expiration started at: " + 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 (String number : blockedList.getNumbers()) { + System.out.println(" - " + number); + } + } } } } else { @@ -823,7 +858,7 @@ public class Main { } private void handleSignalServiceDataMessage(SignalServiceDataMessage message) { - System.out.println("Message timestamp: " + message.getTimestamp()); + System.out.println("Message timestamp: " + formatTimestamp(message.getTimestamp())); if (message.getBody().isPresent()) { System.out.println("Body: " + message.getBody().get()); @@ -856,6 +891,12 @@ public class Main { if (message.isEndSession()) { System.out.println("Is end session"); } + if (message.isExpirationUpdate()) { + System.out.println("Is Expiration update: " + message.isExpirationUpdate()); + } + if (message.getExpiresInSeconds() > 0) { + System.out.println("Expires in: " + message.getExpiresInSeconds() + " seconds"); + } if (message.getAttachments().isPresent()) { System.out.println("Attachments: "); @@ -888,8 +929,8 @@ public class Main { } @Override - public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content) { - super.handleMessage(envelope, content); + public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) { + super.handleMessage(envelope, content, exception); if (!envelope.isReceipt() && content != null && content.getDataMessage().isPresent()) { SignalServiceDataMessage message = content.getDataMessage().get(); @@ -922,4 +963,11 @@ public class Main { } } + + private 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 + df.setTimeZone(tzUTC); + return timestamp + " (" + df.format(date) + ")"; + } }