+ messagePipe = null;
+ }
+ }
+ }
+
+ private void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, boolean ignoreAttachments) {
+ if (content != null) {
+ if (content.getDataMessage().isPresent()) {
+ SignalServiceDataMessage message = content.getDataMessage().get();
+ handleSignalServiceDataMessage(message, false, envelope.getSource(), username, ignoreAttachments);
+ }
+ if (content.getSyncMessage().isPresent()) {
+ SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
+ if (syncMessage.getSent().isPresent()) {
+ SignalServiceDataMessage message = syncMessage.getSent().get().getMessage();
+ handleSignalServiceDataMessage(message, true, envelope.getSource(), syncMessage.getSent().get().getDestination().get(), ignoreAttachments);
+ }
+ if (syncMessage.getRequest().isPresent()) {
+ RequestMessage rm = syncMessage.getRequest().get();
+ if (rm.isContactsRequest()) {
+ try {
+ sendContacts();
+ } catch (UntrustedIdentityException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (rm.isGroupsRequest()) {
+ try {
+ sendGroups();
+ } catch (UntrustedIdentityException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if (syncMessage.getGroups().isPresent()) {
+ File tmpFile = null;
+ try {
+ tmpFile = Util.createTempFile();
+ DeviceGroupsInputStream s = new DeviceGroupsInputStream(retrieveAttachmentAsStream(syncMessage.getGroups().get().asPointer(), tmpFile));
+ DeviceGroup g;
+ while ((g = s.read()) != null) {
+ GroupInfo syncGroup = groupStore.getGroup(g.getId());
+ if (syncGroup == null) {
+ syncGroup = new GroupInfo(g.getId());
+ }
+ if (g.getName().isPresent()) {
+ syncGroup.name = g.getName().get();
+ }
+ syncGroup.members.addAll(g.getMembers());
+ syncGroup.active = g.isActive();
+
+ if (g.getAvatar().isPresent()) {
+ retrieveGroupAvatarAttachment(g.getAvatar().get(), syncGroup.groupId);
+ }
+ groupStore.updateGroup(syncGroup);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (tmpFile != null) {
+ try {
+ Files.delete(tmpFile.toPath());
+ } catch (IOException e) {
+ System.out.println("Failed to delete temp file “" + tmpFile + "”: " + e.getMessage());
+ }
+ }
+ }
+ if (syncMessage.getBlockedList().isPresent()) {
+ // TODO store list of blocked numbers
+ }
+ }
+ if (syncMessage.getContacts().isPresent()) {
+ File tmpFile = null;
+ try {
+ tmpFile = Util.createTempFile();
+ DeviceContactsInputStream s = new DeviceContactsInputStream(retrieveAttachmentAsStream(syncMessage.getContacts().get().asPointer(), tmpFile));
+ DeviceContact c;
+ while ((c = s.read()) != null) {
+ ContactInfo contact = contactStore.getContact(c.getNumber());
+ if (contact == null) {
+ contact = new ContactInfo();
+ contact.number = c.getNumber();
+ }
+ if (c.getName().isPresent()) {
+ contact.name = c.getName().get();
+ }
+ if (c.getColor().isPresent()) {
+ contact.color = c.getColor().get();
+ }
+ contactStore.updateContact(contact);
+
+ if (c.getAvatar().isPresent()) {
+ retrieveContactAvatarAttachment(c.getAvatar().get(), contact.number);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (tmpFile != null) {
+ try {
+ Files.delete(tmpFile.toPath());
+ } catch (IOException e) {
+ System.out.println("Failed to delete temp file “" + tmpFile + "”: " + e.getMessage());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private SignalServiceEnvelope loadEnvelope(File file) throws IOException {
+ try (FileInputStream f = new FileInputStream(file)) {
+ DataInputStream in = new DataInputStream(f);
+ int version = in.readInt();
+ if (version != 1) {
+ return null;
+ }
+ int type = in.readInt();
+ String source = in.readUTF();
+ int sourceDevice = in.readInt();
+ String relay = in.readUTF();
+ long timestamp = in.readLong();
+ byte[] content = null;
+ int contentLen = in.readInt();
+ if (contentLen > 0) {
+ content = new byte[contentLen];
+ in.readFully(content);
+ }
+ byte[] legacyMessage = null;
+ int legacyMessageLen = in.readInt();
+ if (legacyMessageLen > 0) {
+ legacyMessage = new byte[legacyMessageLen];
+ in.readFully(legacyMessage);
+ }
+ return new SignalServiceEnvelope(type, source, sourceDevice, relay, timestamp, legacyMessage, content);
+ }
+ }
+
+ private void storeEnvelope(SignalServiceEnvelope envelope, File file) throws IOException {
+ try (FileOutputStream f = new FileOutputStream(file)) {
+ try (DataOutputStream out = new DataOutputStream(f)) {
+ out.writeInt(1); // version
+ out.writeInt(envelope.getType());
+ out.writeUTF(envelope.getSource());
+ out.writeInt(envelope.getSourceDevice());
+ out.writeUTF(envelope.getRelay());
+ out.writeLong(envelope.getTimestamp());
+ if (envelope.hasContent()) {
+ out.writeInt(envelope.getContent().length);
+ out.write(envelope.getContent());
+ } else {
+ out.writeInt(0);
+ }
+ if (envelope.hasLegacyMessage()) {
+ out.writeInt(envelope.getLegacyMessage().length);
+ out.write(envelope.getLegacyMessage());
+ } else {
+ out.writeInt(0);
+ }
+ }
+ }
+ }
+
+ public File getContactAvatarFile(String number) {
+ return new File(avatarsPath, "contact-" + number);
+ }
+
+ private File retrieveContactAvatarAttachment(SignalServiceAttachment attachment, String number) throws IOException, InvalidMessageException {
+ createPrivateDirectories(avatarsPath);
+ if (attachment.isPointer()) {
+ SignalServiceAttachmentPointer pointer = attachment.asPointer();
+ return retrieveAttachment(pointer, getContactAvatarFile(number), false);
+ } else {
+ SignalServiceAttachmentStream stream = attachment.asStream();
+ return retrieveAttachment(stream, getContactAvatarFile(number));
+ }
+ }
+
+ public File getGroupAvatarFile(byte[] groupId) {
+ return new File(avatarsPath, "group-" + Base64.encodeBytes(groupId).replace("/", "_"));
+ }
+
+ private File retrieveGroupAvatarAttachment(SignalServiceAttachment attachment, byte[] groupId) throws IOException, InvalidMessageException {
+ createPrivateDirectories(avatarsPath);
+ if (attachment.isPointer()) {
+ SignalServiceAttachmentPointer pointer = attachment.asPointer();
+ return retrieveAttachment(pointer, getGroupAvatarFile(groupId), false);
+ } else {
+ SignalServiceAttachmentStream stream = attachment.asStream();
+ return retrieveAttachment(stream, getGroupAvatarFile(groupId));