]> nmode's Git Repositories - signal-cli/commitdiff
Extract static methods from Main
authorAsamK <asamk@gmx.de>
Mon, 19 Nov 2018 21:40:16 +0000 (22:40 +0100)
committerAsamK <asamk@gmx.de>
Mon, 19 Nov 2018 22:00:13 +0000 (23:00 +0100)
src/main/java/org/asamk/signal/DbusReceiveMessageHandler.java [new file with mode: 0644]
src/main/java/org/asamk/signal/GroupIdFormatException.java [new file with mode: 0644]
src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java [new file with mode: 0644]
src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java [new file with mode: 0644]
src/main/java/org/asamk/signal/Main.java
src/main/java/org/asamk/signal/ReceiveMessageHandler.java [new file with mode: 0644]
src/main/java/org/asamk/signal/util/ErrorUtils.java [new file with mode: 0644]
src/main/java/org/asamk/signal/util/Util.java

diff --git a/src/main/java/org/asamk/signal/DbusReceiveMessageHandler.java b/src/main/java/org/asamk/signal/DbusReceiveMessageHandler.java
new file mode 100644 (file)
index 0000000..2ea51e2
--- /dev/null
@@ -0,0 +1,25 @@
+package org.asamk.signal;
+
+import org.asamk.signal.manager.Manager;
+import org.freedesktop.dbus.DBusConnection;
+import org.whispersystems.signalservice.api.messages.SignalServiceContent;
+import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
+
+class DbusReceiveMessageHandler extends ReceiveMessageHandler {
+
+    private final DBusConnection conn;
+    private final String objectPath;
+
+    DbusReceiveMessageHandler(Manager m, DBusConnection conn, final String objectPath) {
+        super(m);
+        this.conn = conn;
+        this.objectPath = objectPath;
+    }
+
+    @Override
+    public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
+        super.handleMessage(envelope, content, exception);
+
+        JsonDbusReceiveMessageHandler.sendReceivedMessageToDbus(envelope, content, conn, objectPath, m);
+    }
+}
diff --git a/src/main/java/org/asamk/signal/GroupIdFormatException.java b/src/main/java/org/asamk/signal/GroupIdFormatException.java
new file mode 100644 (file)
index 0000000..62add53
--- /dev/null
@@ -0,0 +1,10 @@
+package org.asamk.signal;
+
+import java.io.IOException;
+
+public class GroupIdFormatException extends Exception {
+
+    public GroupIdFormatException(String groupId, IOException e) {
+        super("Failed to decode groupId (must be base64) \"" + groupId + "\": " + e.getMessage());
+    }
+}
diff --git a/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java b/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java
new file mode 100644 (file)
index 0000000..533a1ae
--- /dev/null
@@ -0,0 +1,71 @@
+package org.asamk.signal;
+
+import org.asamk.Signal;
+import org.asamk.signal.manager.Manager;
+import org.freedesktop.dbus.DBusConnection;
+import org.freedesktop.dbus.exceptions.DBusException;
+import org.whispersystems.signalservice.api.messages.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
+
+    private final DBusConnection conn;
+
+    private final String objectPath;
+
+    JsonDbusReceiveMessageHandler(Manager m, DBusConnection conn, final String objectPath) {
+        super(m);
+        this.conn = conn;
+        this.objectPath = objectPath;
+    }
+
+    static void sendReceivedMessageToDbus(SignalServiceEnvelope envelope, SignalServiceContent content, DBusConnection conn, final String objectPath, Manager m) {
+        if (envelope.isReceipt()) {
+            try {
+                conn.sendSignal(new Signal.ReceiptReceived(
+                        objectPath,
+                        envelope.getTimestamp(),
+                        envelope.getSource()
+                ));
+            } catch (DBusException e) {
+                e.printStackTrace();
+            }
+        } else if (content != null && content.getDataMessage().isPresent()) {
+            SignalServiceDataMessage message = content.getDataMessage().get();
+
+            if (!message.isEndSession() &&
+                    !(message.getGroupInfo().isPresent() &&
+                            message.getGroupInfo().get().getType() != SignalServiceGroup.Type.DELIVER)) {
+                List<String> attachments = new ArrayList<>();
+                if (message.getAttachments().isPresent()) {
+                    for (SignalServiceAttachment attachment : message.getAttachments().get()) {
+                        if (attachment.isPointer()) {
+                            attachments.add(m.getAttachmentFile(attachment.asPointer().getId()).getAbsolutePath());
+                        }
+                    }
+                }
+
+                try {
+                    conn.sendSignal(new Signal.MessageReceived(
+                            objectPath,
+                            message.getTimestamp(),
+                            envelope.getSource(),
+                            message.getGroupInfo().isPresent() ? message.getGroupInfo().get().getGroupId() : new byte[0],
+                            message.getBody().isPresent() ? message.getBody().get() : "",
+                            attachments));
+                } catch (DBusException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
+        super.handleMessage(envelope, content, exception);
+
+        sendReceivedMessageToDbus(envelope, content, conn, objectPath, m);
+    }
+}
diff --git a/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java b/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java
new file mode 100644 (file)
index 0000000..7ae5d45
--- /dev/null
@@ -0,0 +1,46 @@
+package org.asamk.signal;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.asamk.signal.manager.Manager;
+import org.whispersystems.signalservice.api.messages.SignalServiceContent;
+import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
+
+import java.io.IOException;
+
+class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler {
+
+    final Manager m;
+    private final ObjectMapper jsonProcessor;
+
+    JsonReceiveMessageHandler(Manager m) {
+        this.m = m;
+        this.jsonProcessor = new ObjectMapper();
+        jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // disable autodetect
+        jsonProcessor.enable(SerializationFeature.WRITE_NULL_MAP_VALUES);
+        jsonProcessor.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+        jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
+    }
+
+    @Override
+    public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
+        ObjectNode result = jsonProcessor.createObjectNode();
+        if (exception != null) {
+            result.putPOJO("error", new JsonError(exception));
+        }
+        if (envelope != null) {
+            result.putPOJO("envelope", new JsonMessageEnvelope(envelope, content));
+        }
+        try {
+            jsonProcessor.writeValue(System.out, result);
+            System.out.println();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
index 70a02738ca99ec478ca38e83e310f084b793df08..604c51ee3a017946d5ad9a9ab39dbdb2b9693a98 100644 (file)
  */
 package org.asamk.signal;
 
  */
 package org.asamk.signal;
 
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.databind.node.ObjectNode;
 import net.sourceforge.argparse4j.ArgumentParsers;
 import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.*;
 import net.sourceforge.argparse4j.ArgumentParsers;
 import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.*;
@@ -30,7 +23,6 @@ import org.apache.http.util.TextUtils;
 import org.asamk.Signal;
 import org.asamk.signal.manager.BaseConfig;
 import org.asamk.signal.manager.Manager;
 import org.asamk.Signal;
 import org.asamk.signal.manager.BaseConfig;
 import org.asamk.signal.manager.Manager;
-import org.asamk.signal.storage.contacts.ContactInfo;
 import org.asamk.signal.storage.groups.GroupInfo;
 import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
 import org.asamk.signal.util.DateUtils;
 import org.asamk.signal.storage.groups.GroupInfo;
 import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
 import org.asamk.signal.util.DateUtils;
@@ -43,14 +35,8 @@ import org.freedesktop.dbus.exceptions.DBusException;
 import org.freedesktop.dbus.exceptions.DBusExecutionException;
 import org.whispersystems.libsignal.InvalidKeyException;
 import org.whispersystems.libsignal.util.guava.Optional;
 import org.freedesktop.dbus.exceptions.DBusExecutionException;
 import org.whispersystems.libsignal.InvalidKeyException;
 import org.whispersystems.libsignal.util.guava.Optional;
-import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
-import org.whispersystems.signalservice.api.messages.*;
-import org.whispersystems.signalservice.api.messages.calls.*;
-import org.whispersystems.signalservice.api.messages.multidevice.*;
-import org.whispersystems.signalservice.api.push.SignalServiceAddress;
+import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
 import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions;
 import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions;
-import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException;
-import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
 import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
 import org.whispersystems.signalservice.internal.push.LockedException;
 import org.whispersystems.signalservice.internal.util.Base64;
 import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
 import org.whispersystems.signalservice.internal.push.LockedException;
 import org.whispersystems.signalservice.internal.util.Base64;
@@ -68,6 +54,8 @@ import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
+import static org.asamk.signal.util.ErrorUtils.*;
+
 public class Main {
 
     private static final String SIGNAL_BUSNAME = "org.asamk.Signal";
 public class Main {
 
     private static final String SIGNAL_BUSNAME = "org.asamk.Signal";
@@ -378,7 +366,7 @@ public class Main {
                                 attachments = new ArrayList<>();
                             }
                             if (ns.getString("group") != null) {
                                 attachments = new ArrayList<>();
                             }
                             if (ns.getString("group") != null) {
-                                byte[] groupId = decodeGroupId(ns.getString("group"));
+                                byte[] groupId = Util.decodeGroupId(ns.getString("group"));
                                 ts.sendGroupMessage(messageText, attachments, groupId);
                             } else {
                                 ts.sendMessage(messageText, attachments, ns.<String>getList("recipient"));
                                 ts.sendGroupMessage(messageText, attachments, groupId);
                             } else {
                                 ts.sendMessage(messageText, attachments, ns.<String>getList("recipient"));
@@ -405,6 +393,9 @@ public class Main {
                         } catch (DBusExecutionException e) {
                             handleDBusExecutionException(e);
                             return 1;
                         } catch (DBusExecutionException e) {
                             handleDBusExecutionException(e);
                             return 1;
+                        } catch (GroupIdFormatException e) {
+                            handleGroupIdFormatException(e);
+                            return 1;
                         }
                     }
 
                         }
                     }
 
@@ -488,7 +479,7 @@ public class Main {
                     }
 
                     try {
                     }
 
                     try {
-                        m.sendQuitGroupMessage(decodeGroupId(ns.getString("group")));
+                        m.sendQuitGroupMessage(Util.decodeGroupId(ns.getString("group")));
                     } catch (IOException e) {
                         handleIOException(e);
                         return 3;
                     } catch (IOException e) {
                         handleIOException(e);
                         return 3;
@@ -504,6 +495,9 @@ public class Main {
                     } catch (NotAGroupMemberException e) {
                         handleNotAGroupMemberException(e);
                         return 1;
                     } catch (NotAGroupMemberException e) {
                         handleNotAGroupMemberException(e);
                         return 1;
+                    } catch (GroupIdFormatException e) {
+                        handleGroupIdFormatException(e);
+                        return 1;
                     }
 
                     break;
                     }
 
                     break;
@@ -516,7 +510,7 @@ public class Main {
                     try {
                         byte[] groupId = null;
                         if (ns.getString("group") != null) {
                     try {
                         byte[] groupId = null;
                         if (ns.getString("group") != null) {
-                            groupId = decodeGroupId(ns.getString("group"));
+                            groupId = Util.decodeGroupId(ns.getString("group"));
                         }
                         if (groupId == null) {
                             groupId = new byte[0];
                         }
                         if (groupId == null) {
                             groupId = new byte[0];
@@ -553,6 +547,9 @@ public class Main {
                     } catch (EncapsulatedExceptions e) {
                         handleEncapsulatedExceptions(e);
                         return 3;
                     } catch (EncapsulatedExceptions e) {
                         handleEncapsulatedExceptions(e);
                         return 3;
+                    } catch (GroupIdFormatException e) {
+                        handleGroupIdFormatException(e);
+                        return 1;
                     }
 
                     break;
                     }
 
                     break;
@@ -674,7 +671,7 @@ public class Main {
                         }
                         ignoreAttachments = ns.getBoolean("ignore_attachments");
                         try {
                         }
                         ignoreAttachments = ns.getBoolean("ignore_attachments");
                         try {
-                            m.receiveMessages(1, TimeUnit.HOURS, false, ignoreAttachments, ns.getBoolean("json") ? new JsonDbusReceiveMessageHandler(m, conn) : new DbusReceiveMessageHandler(m, conn));
+                            m.receiveMessages(1, TimeUnit.HOURS, false, ignoreAttachments, ns.getBoolean("json") ? new JsonDbusReceiveMessageHandler(m, conn, Main.SIGNAL_OBJECTPATH) : new DbusReceiveMessageHandler(m, conn, Main.SIGNAL_OBJECTPATH));
                         } catch (IOException e) {
                             System.err.println("Error while receiving messages: " + e.getMessage());
                             return 3;
                         } catch (IOException e) {
                             System.err.println("Error while receiving messages: " + e.getMessage());
                             return 3;
@@ -714,33 +711,6 @@ public class Main {
         }
     }
 
         }
     }
 
-    private static void handleGroupNotFoundException(GroupNotFoundException e) {
-        System.err.println("Failed to send to group: " + e.getMessage());
-        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.");
-    }
-
-    private static byte[] decodeGroupId(String groupId) {
-        try {
-            return Base64.decode(groupId);
-        } catch (IOException e) {
-            System.err.println("Failed to decode groupId (must be base64) \"" + groupId + "\": " + e.getMessage());
-            System.err.println("Aborting sending.");
-            System.exit(1);
-            return null;
-        }
-    }
-
     private static Namespace parseArgs(String[] args) {
         ArgumentParser parser = ArgumentParsers.newFor("signal-cli")
                 .build()
     private static Namespace parseArgs(String[] args) {
         ArgumentParser parser = ArgumentParsers.newFor("signal-cli")
                 .build()
@@ -912,398 +882,4 @@ public class Main {
             return null;
         }
     }
             return null;
         }
     }
-
-    private 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");
-    }
-
-    private static void handleEncapsulatedExceptions(EncapsulatedExceptions e) {
-        System.err.println("Failed to send (some) messages:");
-        for (NetworkFailureException n : e.getNetworkExceptions()) {
-            System.err.println("Network failure for \"" + n.getE164number() + "\": " + n.getMessage());
-        }
-        for (UnregisteredUserException n : e.getUnregisteredUserExceptions()) {
-            System.err.println("Unregistered user \"" + n.getE164Number() + "\": " + n.getMessage());
-        }
-        for (UntrustedIdentityException n : e.getUntrustedIdentityExceptions()) {
-            System.err.println("Untrusted Identity for \"" + n.getE164Number() + "\": " + n.getMessage());
-        }
-    }
-
-    private static void handleIOException(IOException e) {
-        System.err.println("Failed to send message: " + e.getMessage());
-    }
-
-    private static class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
-
-        final Manager m;
-
-        ReceiveMessageHandler(Manager m) {
-            this.m = m;
-        }
-
-        @Override
-        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: " + DateUtils.formatTimestamp(envelope.getTimestamp()));
-            if (envelope.isUnidentifiedSender()) {
-                System.out.println("Sent by unidentified/sealed sender");
-            }
-
-            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 {
-                    if (content.getDataMessage().isPresent()) {
-                        SignalServiceDataMessage message = content.getDataMessage().get();
-                        handleSignalServiceDataMessage(message);
-                    }
-                    if (content.getSyncMessage().isPresent()) {
-                        System.out.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());
-                        }
-                        if (syncMessage.getGroups().isPresent()) {
-                            System.out.println("Received sync groups");
-                            printAttachment(syncMessage.getGroups().get());
-                        }
-                        if (syncMessage.getRead().isPresent()) {
-                            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: " + 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.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();
-                                ContactInfo destContact = m.getContact(dest);
-                                to = (destContact == null ? "" : "“" + destContact.name + "” ") + dest;
-                            } 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 (String number : blockedList.getNumbers()) {
-                                System.out.println(" - " + number);
-                            }
-                        }
-                        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 (content.getCallMessage().isPresent()) {
-                        System.out.println("Received a call message");
-                        SignalServiceCallMessage callMessage = content.getCallMessage().get();
-                        if (callMessage.getAnswerMessage().isPresent()) {
-                            AnswerMessage answerMessage = callMessage.getAnswerMessage().get();
-                            System.out.println("Answer message: " + answerMessage.getId() + ": " + answerMessage.getDescription());
-                        }
-                        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<IceUpdateMessage> 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.getDescription());
-                        }
-                    }
-                    if (content.getReceiptMessage().isPresent()) {
-                        System.out.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");
-                        }
-                        System.out.println(" - Timestamps:");
-                        for (long timestamp : receiptMessage.getTimestamps()) {
-                            System.out.println("    " + DateUtils.formatTimestamp(timestamp));
-                        }
-                    }
-                    if (content.getTypingMessage().isPresent()) {
-                        System.out.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()) {
-                            GroupInfo group = m.getGroup(typingMessage.getGroupId().get());
-                            if (group != null) {
-                                System.out.println("  Name: " + group.name);
-                            } else {
-                                System.out.println("  Name: <Unknown group>");
-                            }
-                        }
-                    }
-                }
-            } else {
-                System.out.println("Unknown message received.");
-            }
-            System.out.println();
-        }
-
-        private void handleSignalServiceDataMessage(SignalServiceDataMessage message) {
-            System.out.println("Message timestamp: " + DateUtils.formatTimestamp(message.getTimestamp()));
-
-            if (message.getBody().isPresent()) {
-                System.out.println("Body: " + message.getBody().get());
-            }
-            if (message.getGroupInfo().isPresent()) {
-                SignalServiceGroup groupInfo = message.getGroupInfo().get();
-                System.out.println("Group info:");
-                System.out.println("  Id: " + Base64.encodeBytes(groupInfo.getGroupId()));
-                if (groupInfo.getType() == SignalServiceGroup.Type.UPDATE && groupInfo.getName().isPresent()) {
-                    System.out.println("  Name: " + groupInfo.getName().get());
-                } else {
-                    GroupInfo group = m.getGroup(groupInfo.getGroupId());
-                    if (group != null) {
-                        System.out.println("  Name: " + group.name);
-                    } else {
-                        System.out.println("  Name: <Unknown group>");
-                    }
-                }
-                System.out.println("  Type: " + groupInfo.getType());
-                if (groupInfo.getMembers().isPresent()) {
-                    for (String member : groupInfo.getMembers().get()) {
-                        System.out.println("  Member: " + member);
-                    }
-                }
-                if (groupInfo.getAvatar().isPresent()) {
-                    System.out.println("  Avatar:");
-                    printAttachment(groupInfo.getAvatar().get());
-                }
-            }
-            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.getProfileKey().isPresent()) {
-                System.out.println("Profile key update, key length:" + message.getProfileKey().get().length);
-            }
-
-            if (message.getQuote().isPresent()) {
-                SignalServiceDataMessage.Quote quote = message.getQuote().get();
-                System.out.println("Quote: (" + quote.getId() + ")");
-                System.out.println(" Author: " + quote.getAuthor().getNumber());
-                System.out.println(" Text: " + quote.getText());
-                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 (attachment.getThumbnail() != null) {
-                            printAttachment(attachment.getThumbnail());
-                        }
-                    }
-                }
-            }
-
-            if (message.getAttachments().isPresent()) {
-                System.out.println("Attachments: ");
-                for (SignalServiceAttachment attachment : message.getAttachments().get()) {
-                    printAttachment(attachment);
-                }
-            }
-        }
-
-        private void printAttachment(SignalServiceAttachment attachment) {
-            System.out.println("- " + attachment.getContentType() + " (" + (attachment.isPointer() ? "Pointer" : "") + (attachment.isStream() ? "Stream" : "") + ")");
-            if (attachment.isPointer()) {
-                final SignalServiceAttachmentPointer pointer = attachment.asPointer();
-                System.out.println("  Id: " + pointer.getId() + " Key length: " + pointer.getKey().length);
-                System.out.println("  Filename: " + (pointer.getFileName().isPresent() ? pointer.getFileName().get() : "-"));
-                System.out.println("  Size: " + (pointer.getSize().isPresent() ? pointer.getSize().get() + " bytes" : "<unavailable>") + (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());
-                File file = m.getAttachmentFile(pointer.getId());
-                if (file.exists()) {
-                    System.out.println("  Stored plaintext in: " + file);
-                }
-            }
-        }
-    }
-
-    private static class DbusReceiveMessageHandler extends ReceiveMessageHandler {
-
-        final DBusConnection conn;
-
-        DbusReceiveMessageHandler(Manager m, DBusConnection conn) {
-            super(m);
-            this.conn = conn;
-        }
-
-        @Override
-        public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
-            super.handleMessage(envelope, content, exception);
-
-            JsonDbusReceiveMessageHandler.sendReceivedMessageToDbus(envelope, content, conn, m);
-        }
-    }
-
-    private static class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler {
-
-        final Manager m;
-        final ObjectMapper jsonProcessor;
-
-        JsonReceiveMessageHandler(Manager m) {
-            this.m = m;
-            this.jsonProcessor = new ObjectMapper();
-            jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // disable autodetect
-            jsonProcessor.enable(SerializationFeature.WRITE_NULL_MAP_VALUES);
-            jsonProcessor.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
-            jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
-        }
-
-        @Override
-        public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
-            ObjectNode result = jsonProcessor.createObjectNode();
-            if (exception != null) {
-                result.putPOJO("error", new JsonError(exception));
-            }
-            if (envelope != null) {
-                result.putPOJO("envelope", new JsonMessageEnvelope(envelope, content));
-            }
-            try {
-                jsonProcessor.writeValue(System.out, result);
-                System.out.println();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    private static class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
-
-        final DBusConnection conn;
-
-        JsonDbusReceiveMessageHandler(Manager m, DBusConnection conn) {
-            super(m);
-            this.conn = conn;
-        }
-
-        private static void sendReceivedMessageToDbus(SignalServiceEnvelope envelope, SignalServiceContent content, DBusConnection conn, Manager m) {
-            if (envelope.isReceipt()) {
-                try {
-                    conn.sendSignal(new Signal.ReceiptReceived(
-                            SIGNAL_OBJECTPATH,
-                            envelope.getTimestamp(),
-                            envelope.getSource()
-                    ));
-                } catch (DBusException e) {
-                    e.printStackTrace();
-                }
-            } else if (content != null && content.getDataMessage().isPresent()) {
-                SignalServiceDataMessage message = content.getDataMessage().get();
-
-                if (!message.isEndSession() &&
-                        !(message.getGroupInfo().isPresent() &&
-                                message.getGroupInfo().get().getType() != SignalServiceGroup.Type.DELIVER)) {
-                    List<String> attachments = new ArrayList<>();
-                    if (message.getAttachments().isPresent()) {
-                        for (SignalServiceAttachment attachment : message.getAttachments().get()) {
-                            if (attachment.isPointer()) {
-                                attachments.add(m.getAttachmentFile(attachment.asPointer().getId()).getAbsolutePath());
-                            }
-                        }
-                    }
-
-                    try {
-                        conn.sendSignal(new Signal.MessageReceived(
-                                SIGNAL_OBJECTPATH,
-                                message.getTimestamp(),
-                                envelope.getSource(),
-                                message.getGroupInfo().isPresent() ? message.getGroupInfo().get().getGroupId() : new byte[0],
-                                message.getBody().isPresent() ? message.getBody().get() : "",
-                                attachments));
-                    } catch (DBusException e) {
-                        e.printStackTrace();
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
-            super.handleMessage(envelope, content, exception);
-
-            sendReceivedMessageToDbus(envelope, content, conn, m);
-        }
-    }
 }
 }
diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java
new file mode 100644 (file)
index 0000000..5c57853
--- /dev/null
@@ -0,0 +1,279 @@
+package org.asamk.signal;
+
+import org.asamk.signal.manager.Manager;
+import org.asamk.signal.storage.contacts.ContactInfo;
+import org.asamk.signal.storage.groups.GroupInfo;
+import org.asamk.signal.util.DateUtils;
+import org.asamk.signal.util.Util;
+import org.whispersystems.signalservice.api.messages.*;
+import org.whispersystems.signalservice.api.messages.calls.*;
+import org.whispersystems.signalservice.api.messages.multidevice.*;
+import org.whispersystems.signalservice.api.push.SignalServiceAddress;
+import org.whispersystems.signalservice.internal.util.Base64;
+
+import java.io.File;
+import java.util.List;
+
+class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
+
+    final Manager m;
+
+    ReceiveMessageHandler(Manager m) {
+        this.m = m;
+    }
+
+    @Override
+    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: " + DateUtils.formatTimestamp(envelope.getTimestamp()));
+        if (envelope.isUnidentifiedSender()) {
+            System.out.println("Sent by unidentified/sealed sender");
+        }
+
+        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 {
+                if (content.getDataMessage().isPresent()) {
+                    SignalServiceDataMessage message = content.getDataMessage().get();
+                    handleSignalServiceDataMessage(message);
+                }
+                if (content.getSyncMessage().isPresent()) {
+                    System.out.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());
+                    }
+                    if (syncMessage.getGroups().isPresent()) {
+                        System.out.println("Received sync groups");
+                        printAttachment(syncMessage.getGroups().get());
+                    }
+                    if (syncMessage.getRead().isPresent()) {
+                        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: " + 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.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();
+                            ContactInfo destContact = m.getContact(dest);
+                            to = (destContact == null ? "" : "“" + destContact.name + "” ") + dest;
+                        } 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 (String number : blockedList.getNumbers()) {
+                            System.out.println(" - " + number);
+                        }
+                    }
+                    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 (content.getCallMessage().isPresent()) {
+                    System.out.println("Received a call message");
+                    SignalServiceCallMessage callMessage = content.getCallMessage().get();
+                    if (callMessage.getAnswerMessage().isPresent()) {
+                        AnswerMessage answerMessage = callMessage.getAnswerMessage().get();
+                        System.out.println("Answer message: " + answerMessage.getId() + ": " + answerMessage.getDescription());
+                    }
+                    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<IceUpdateMessage> 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.getDescription());
+                    }
+                }
+                if (content.getReceiptMessage().isPresent()) {
+                    System.out.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");
+                    }
+                    System.out.println(" - Timestamps:");
+                    for (long timestamp : receiptMessage.getTimestamps()) {
+                        System.out.println("    " + DateUtils.formatTimestamp(timestamp));
+                    }
+                }
+                if (content.getTypingMessage().isPresent()) {
+                    System.out.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()) {
+                        GroupInfo group = m.getGroup(typingMessage.getGroupId().get());
+                        if (group != null) {
+                            System.out.println("  Name: " + group.name);
+                        } else {
+                            System.out.println("  Name: <Unknown group>");
+                        }
+                    }
+                }
+            }
+        } else {
+            System.out.println("Unknown message received.");
+        }
+        System.out.println();
+    }
+
+    private void handleSignalServiceDataMessage(SignalServiceDataMessage message) {
+        System.out.println("Message timestamp: " + DateUtils.formatTimestamp(message.getTimestamp()));
+
+        if (message.getBody().isPresent()) {
+            System.out.println("Body: " + message.getBody().get());
+        }
+        if (message.getGroupInfo().isPresent()) {
+            SignalServiceGroup groupInfo = message.getGroupInfo().get();
+            System.out.println("Group info:");
+            System.out.println("  Id: " + Base64.encodeBytes(groupInfo.getGroupId()));
+            if (groupInfo.getType() == SignalServiceGroup.Type.UPDATE && groupInfo.getName().isPresent()) {
+                System.out.println("  Name: " + groupInfo.getName().get());
+            } else {
+                GroupInfo group = m.getGroup(groupInfo.getGroupId());
+                if (group != null) {
+                    System.out.println("  Name: " + group.name);
+                } else {
+                    System.out.println("  Name: <Unknown group>");
+                }
+            }
+            System.out.println("  Type: " + groupInfo.getType());
+            if (groupInfo.getMembers().isPresent()) {
+                for (String member : groupInfo.getMembers().get()) {
+                    System.out.println("  Member: " + member);
+                }
+            }
+            if (groupInfo.getAvatar().isPresent()) {
+                System.out.println("  Avatar:");
+                printAttachment(groupInfo.getAvatar().get());
+            }
+        }
+        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.getProfileKey().isPresent()) {
+            System.out.println("Profile key update, key length:" + message.getProfileKey().get().length);
+        }
+
+        if (message.getQuote().isPresent()) {
+            SignalServiceDataMessage.Quote quote = message.getQuote().get();
+            System.out.println("Quote: (" + quote.getId() + ")");
+            System.out.println(" Author: " + quote.getAuthor().getNumber());
+            System.out.println(" Text: " + quote.getText());
+            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 (attachment.getThumbnail() != null) {
+                        printAttachment(attachment.getThumbnail());
+                    }
+                }
+            }
+        }
+
+        if (message.getAttachments().isPresent()) {
+            System.out.println("Attachments: ");
+            for (SignalServiceAttachment attachment : message.getAttachments().get()) {
+                printAttachment(attachment);
+            }
+        }
+    }
+
+    private void printAttachment(SignalServiceAttachment attachment) {
+        System.out.println("- " + attachment.getContentType() + " (" + (attachment.isPointer() ? "Pointer" : "") + (attachment.isStream() ? "Stream" : "") + ")");
+        if (attachment.isPointer()) {
+            final SignalServiceAttachmentPointer pointer = attachment.asPointer();
+            System.out.println("  Id: " + pointer.getId() + " Key length: " + pointer.getKey().length);
+            System.out.println("  Filename: " + (pointer.getFileName().isPresent() ? pointer.getFileName().get() : "-"));
+            System.out.println("  Size: " + (pointer.getSize().isPresent() ? pointer.getSize().get() + " bytes" : "<unavailable>") + (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());
+            File file = m.getAttachmentFile(pointer.getId());
+            if (file.exists()) {
+                System.out.println("  Stored plaintext in: " + file);
+            }
+        }
+    }
+}
diff --git a/src/main/java/org/asamk/signal/util/ErrorUtils.java b/src/main/java/org/asamk/signal/util/ErrorUtils.java
new file mode 100644 (file)
index 0000000..99fc409
--- /dev/null
@@ -0,0 +1,62 @@
+package org.asamk.signal.util;
+
+import org.asamk.signal.GroupIdFormatException;
+import org.asamk.signal.GroupNotFoundException;
+import org.asamk.signal.NotAGroupMemberException;
+import org.freedesktop.dbus.exceptions.DBusExecutionException;
+import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
+import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions;
+import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException;
+import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
+
+import java.io.IOException;
+
+public class ErrorUtils {
+
+    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");
+    }
+
+    public static void handleEncapsulatedExceptions(EncapsulatedExceptions e) {
+        System.err.println("Failed to send (some) messages:");
+        for (NetworkFailureException n : e.getNetworkExceptions()) {
+            System.err.println("Network failure for \"" + n.getE164number() + "\": " + n.getMessage());
+        }
+        for (UnregisteredUserException n : e.getUnregisteredUserExceptions()) {
+            System.err.println("Unregistered user \"" + n.getE164Number() + "\": " + n.getMessage());
+        }
+        for (UntrustedIdentityException n : e.getUntrustedIdentityExceptions()) {
+            System.err.println("Untrusted Identity for \"" + n.getE164Number() + "\": " + n.getMessage());
+        }
+    }
+
+    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 handleDBusExecutionException(DBusExecutionException e) {
+        System.err.println("Cannot connect to dbus: " + e.getMessage());
+        System.err.println("Aborting.");
+    }
+
+    public static void handleGroupIdFormatException(GroupIdFormatException e) {
+        System.err.println(e.getMessage());
+        System.err.println("Aborting sending.");
+    }
+}
index 5a1dcddafaab3d8c28eb851c71b67d190ab07511..e7a6866842ed50156373e96bcfe29c16f428983b 100644 (file)
@@ -1,7 +1,10 @@
 package org.asamk.signal.util;
 
 import com.fasterxml.jackson.databind.JsonNode;
 package org.asamk.signal.util;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import org.asamk.signal.GroupIdFormatException;
+import org.whispersystems.signalservice.internal.util.Base64;
 
 
+import java.io.IOException;
 import java.io.InvalidObjectException;
 
 public class Util {
 import java.io.InvalidObjectException;
 
 public class Util {
@@ -39,4 +42,12 @@ public class Util {
 
         return node;
     }
 
         return node;
     }
+
+    public static byte[] decodeGroupId(String groupId) throws GroupIdFormatException {
+        try {
+            return Base64.decode(groupId);
+        } catch (IOException e) {
+            throw new GroupIdFormatException(groupId, e);
+        }
+    }
 }
 }