X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/82cecfff85ef29e627d4238e3237222b492d5248..c5cf78a50ad213fb21728f4d648de51dfac7f07e:/src/main/java/org/asamk/signal/Manager.java diff --git a/src/main/java/org/asamk/signal/Manager.java b/src/main/java/org/asamk/signal/Manager.java index 1aefc252..6598bfde 100644 --- a/src/main/java/org/asamk/signal/Manager.java +++ b/src/main/java/org/asamk/signal/Manager.java @@ -663,34 +663,75 @@ class Manager implements Signal { } } + if (avatarFile != null) { + createPrivateDirectories(avatarsPath); + File aFile = getGroupAvatarFile(g.groupId); + Files.copy(Paths.get(avatarFile), aFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + + groupStore.updateGroup(g); + + SignalServiceDataMessage.Builder messageBuilder = getGroupUpdateMessageBuilder(g); + + // Don't send group message to ourself + final List membersSend = new ArrayList<>(g.members); + membersSend.remove(this.username); + sendMessage(messageBuilder, membersSend); + return g.groupId; + } + + private void sendUpdateGroupMessage(byte[] groupId, String recipient) throws IOException, EncapsulatedExceptions { + if (groupId == null) { + return; + } + GroupInfo g = getGroupForSending(groupId); + + if (!g.members.contains(recipient)) { + return; + } + + SignalServiceDataMessage.Builder messageBuilder = getGroupUpdateMessageBuilder(g); + + // Send group message only to the recipient who requested it + final List membersSend = new ArrayList<>(); + membersSend.add(recipient); + sendMessage(messageBuilder, membersSend); + } + + private SignalServiceDataMessage.Builder getGroupUpdateMessageBuilder(GroupInfo g) { SignalServiceGroup.Builder group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.UPDATE) .withId(g.groupId) .withName(g.name) .withMembers(new ArrayList<>(g.members)); File aFile = getGroupAvatarFile(g.groupId); - if (avatarFile != null) { - createPrivateDirectories(avatarsPath); - Files.copy(Paths.get(avatarFile), aFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } if (aFile.exists()) { try { group.withAvatar(createAttachment(aFile)); } catch (IOException e) { - throw new AttachmentInvalidException(avatarFile, e); + throw new AttachmentInvalidException(aFile.toString(), e); } } - groupStore.updateGroup(g); + return SignalServiceDataMessage.newBuilder() + .asGroupMessage(group.build()); + } + + private void sendGroupInfoRequest(byte[] groupId, String recipient) throws IOException, EncapsulatedExceptions { + if (groupId == null) { + return; + } + + SignalServiceGroup.Builder group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.REQUEST_INFO) + .withId(groupId); SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() .asGroupMessage(group.build()); - // Don't send group message to ourself - final List membersSend = new ArrayList<>(g.members); - membersSend.remove(this.username); + // Send group info request message to the recipient who sent us a message with this groupId + final List membersSend = new ArrayList<>(); + membersSend.add(recipient); sendMessage(messageBuilder, membersSend); - return g.groupId; } @Override @@ -847,10 +888,9 @@ class Manager implements Signal { if (message.getGroupInfo().isPresent()) { SignalServiceGroup groupInfo = message.getGroupInfo().get(); threadId = Base64.encodeBytes(groupInfo.getGroupId()); + GroupInfo group = groupStore.getGroup(groupInfo.getGroupId()); switch (groupInfo.getType()) { case UPDATE: - GroupInfo group; - group = groupStore.getGroup(groupInfo.getGroupId()); if (group == null) { group = new GroupInfo(groupInfo.getGroupId()); } @@ -877,14 +917,37 @@ class Manager implements Signal { groupStore.updateGroup(group); break; case DELIVER: + if (group == null) { + try { + sendGroupInfoRequest(groupInfo.getGroupId(), source); + } catch (IOException | EncapsulatedExceptions e) { + e.printStackTrace(); + } + } break; case QUIT: - group = groupStore.getGroup(groupInfo.getGroupId()); - if (group != null) { + if (group == null) { + try { + sendGroupInfoRequest(groupInfo.getGroupId(), source); + } catch (IOException | EncapsulatedExceptions e) { + e.printStackTrace(); + } + } else { group.members.remove(source); groupStore.updateGroup(group); } break; + case REQUEST_INFO: + if (group != null) { + try { + sendUpdateGroupMessage(groupInfo.getGroupId(), source); + } catch (IOException | EncapsulatedExceptions e) { + e.printStackTrace(); + } catch (NotAGroupMemberException e) { + // We have left this group, so don't send a group update message + } + } + break; } } else { if (isSync) { @@ -930,7 +993,6 @@ class Manager implements Signal { continue; } - String sender = dir.getName(); for (final File fileEntry : dir.listFiles()) { if (!fileEntry.isFile()) { continue; @@ -956,12 +1018,16 @@ class Manager implements Signal { } save(); handler.handleMessage(envelope, content, null); - fileEntry.delete(); + try { + Files.delete(fileEntry.toPath()); + } catch (IOException e) { + System.out.println("Failed to delete cached message file “" + fileEntry + "”: " + e.getMessage()); + } } } } - public void receiveMessages(int timeoutSeconds, boolean returnOnTimeout, ReceiveMessageHandler handler) throws IOException { + public void receiveMessages(long timeout, TimeUnit unit, boolean returnOnTimeout, ReceiveMessageHandler handler) throws IOException { retryFailedReceivedMessages(handler); final SignalServiceMessageReceiver messageReceiver = new SignalServiceMessageReceiver(URL, TRUST_STORE, username, password, deviceId, signalingKey, USER_AGENT); SignalServiceMessagePipe messagePipe = null; @@ -975,7 +1041,7 @@ class Manager implements Signal { Exception exception = null; final long now = new Date().getTime(); try { - envelope = messagePipe.read(timeoutSeconds, TimeUnit.SECONDS, new SignalServiceMessagePipe.MessagePipeCallback() { + envelope = messagePipe.read(timeout, unit, new SignalServiceMessagePipe.MessagePipeCallback() { @Override public void onMessage(SignalServiceEnvelope envelope) { // store message on disk, before acknowledging receipt to the server @@ -1006,12 +1072,12 @@ class Manager implements Signal { save(); handler.handleMessage(envelope, content, exception); if (exception == null || !(exception instanceof org.whispersystems.libsignal.UntrustedIdentityException)) { + File cacheFile = null; try { - File cacheFile = getMessageCacheFile(envelope.getSource(), now, envelope.getTimestamp()); - cacheFile.delete(); + cacheFile = getMessageCacheFile(envelope.getSource(), now, envelope.getTimestamp()); + Files.delete(cacheFile.toPath()); } catch (IOException e) { - // Ignoring - return; + System.out.println("Failed to delete cached message file “" + cacheFile + "”: " + e.getMessage()); } } } @@ -1051,8 +1117,10 @@ class Manager implements Signal { } } if (syncMessage.getGroups().isPresent()) { + File tmpFile = null; try { - DeviceGroupsInputStream s = new DeviceGroupsInputStream(retrieveAttachmentAsStream(syncMessage.getGroups().get().asPointer())); + 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()); @@ -1072,14 +1140,24 @@ class Manager implements Signal { } } 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 { - DeviceContactsInputStream s = new DeviceContactsInputStream(retrieveAttachmentAsStream(syncMessage.getContacts().get().asPointer())); + 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()); @@ -1101,6 +1179,14 @@ class Manager implements Signal { } } 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()); + } + } } } } @@ -1242,7 +1328,7 @@ class Manager implements Signal { final SignalServiceMessageReceiver messageReceiver = new SignalServiceMessageReceiver(URL, TRUST_STORE, username, password, deviceId, signalingKey, USER_AGENT); - File tmpFile = File.createTempFile("ts_attach_" + pointer.getId(), ".tmp"); + File tmpFile = Util.createTempFile(); InputStream input = messageReceiver.retrieveAttachment(pointer, tmpFile); OutputStream output = null; @@ -1261,19 +1347,19 @@ class Manager implements Signal { if (output != null) { output.close(); } - if (!tmpFile.delete()) { - System.err.println("Failed to delete temp file: " + tmpFile); + input.close(); + try { + Files.delete(tmpFile.toPath()); + } catch (IOException e) { + System.out.println("Failed to delete temp file “" + tmpFile + "”: " + e.getMessage()); } } return outputFile; } - private InputStream retrieveAttachmentAsStream(SignalServiceAttachmentPointer pointer) throws IOException, InvalidMessageException { + private InputStream retrieveAttachmentAsStream(SignalServiceAttachmentPointer pointer, File tmpFile) throws IOException, InvalidMessageException { final SignalServiceMessageReceiver messageReceiver = new SignalServiceMessageReceiver(URL, TRUST_STORE, username, password, deviceId, signalingKey, USER_AGENT); - File file = File.createTempFile("ts_tmp", "tmp"); - file.deleteOnExit(); - - return messageReceiver.retrieveAttachment(pointer, file); + return messageReceiver.retrieveAttachment(pointer, tmpFile); } private String canonicalizeNumber(String number) throws InvalidNumberException { @@ -1292,7 +1378,7 @@ class Manager implements Signal { } private void sendGroups() throws IOException, UntrustedIdentityException { - File groupsFile = File.createTempFile("multidevice-group-update", ".tmp"); + File groupsFile = Util.createTempFile(); try { DeviceGroupsOutputStream out = new DeviceGroupsOutputStream(new FileOutputStream(groupsFile)); @@ -1307,22 +1393,27 @@ class Manager implements Signal { } if (groupsFile.exists() && groupsFile.length() > 0) { - FileInputStream contactsFileStream = new FileInputStream(groupsFile); - SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder() - .withStream(contactsFileStream) - .withContentType("application/octet-stream") - .withLength(groupsFile.length()) - .build(); - - sendSyncMessage(SignalServiceSyncMessage.forGroups(attachmentStream)); + try (FileInputStream groupsFileStream = new FileInputStream(groupsFile)) { + SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder() + .withStream(groupsFileStream) + .withContentType("application/octet-stream") + .withLength(groupsFile.length()) + .build(); + + sendSyncMessage(SignalServiceSyncMessage.forGroups(attachmentStream)); + } } } finally { - groupsFile.delete(); + try { + Files.delete(groupsFile.toPath()); + } catch (IOException e) { + System.out.println("Failed to delete temp file “" + groupsFile + "”: " + e.getMessage()); + } } } private void sendContacts() throws IOException, UntrustedIdentityException { - File contactsFile = File.createTempFile("multidevice-contact-update", ".tmp"); + File contactsFile = Util.createTempFile(); try { DeviceContactsOutputStream out = new DeviceContactsOutputStream(new FileOutputStream(contactsFile)); @@ -1336,17 +1427,22 @@ class Manager implements Signal { } if (contactsFile.exists() && contactsFile.length() > 0) { - FileInputStream contactsFileStream = new FileInputStream(contactsFile); - SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder() - .withStream(contactsFileStream) - .withContentType("application/octet-stream") - .withLength(contactsFile.length()) - .build(); - - sendSyncMessage(SignalServiceSyncMessage.forContacts(attachmentStream)); + try (FileInputStream contactsFileStream = new FileInputStream(contactsFile)) { + SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder() + .withStream(contactsFileStream) + .withContentType("application/octet-stream") + .withLength(contactsFile.length()) + .build(); + + sendSyncMessage(SignalServiceSyncMessage.forContacts(attachmentStream)); + } } } finally { - contactsFile.delete(); + try { + Files.delete(contactsFile.toPath()); + } catch (IOException e) { + System.out.println("Failed to delete temp file “" + contactsFile + "”: " + e.getMessage()); + } } }