org.whispersystems.signalservice.api.messages.SignalServiceDataMessage Java Examples

The following examples show how to use org.whispersystems.signalservice.api.messages.SignalServiceDataMessage. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source Project: mollyim-android   Author: mollyim   File: SignalServiceMessageSender.java    License: GNU General Public License v3.0 6 votes vote down vote up
/**
 * Send a message to a group.
 *
 * @param recipients The group members.
 * @param message The group message.
 * @throws IOException
 */
public List<SendMessageResult> sendMessage(List<SignalServiceAddress>             recipients,
                                           List<Optional<UnidentifiedAccessPair>> unidentifiedAccess,
                                           boolean                                isRecipientUpdate,
                                           SignalServiceDataMessage               message)
    throws IOException, UntrustedIdentityException
{
  byte[]                  content            = createMessageContent(message);
  long                    timestamp          = message.getTimestamp();
  List<SendMessageResult> results            = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false);
  boolean                 needsSyncInResults = false;

  for (SendMessageResult result : results) {
    if (result.getSuccess() != null && result.getSuccess().isNeedsSync()) {
      needsSyncInResults = true;
      break;
    }
  }

  if (needsSyncInResults || isMultiDevice.get()) {
    byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.<SignalServiceAddress>absent(), timestamp, results, isRecipientUpdate);
    sendMessage(localAddress, Optional.<UnidentifiedAccess>absent(), timestamp, syncMessage, false);
  }

  return results;
}
 
Example #2
Source Project: mollyim-android   Author: mollyim   File: SentTranscriptMessage.java    License: GNU General Public License v3.0 6 votes vote down vote up
public SentTranscriptMessage(Optional<SignalServiceAddress> destination, long timestamp, SignalServiceDataMessage message,
                             long expirationStartTimestamp, Map<SignalServiceAddress, Boolean> unidentifiedStatus,
                             boolean isRecipientUpdate)
{
  this.destination              = destination;
  this.timestamp                = timestamp;
  this.message                  = message;
  this.expirationStartTimestamp = expirationStartTimestamp;
  this.unidentifiedStatusByUuid = new HashMap<>();
  this.unidentifiedStatusByE164 = new HashMap<>();
  this.recipients               = unidentifiedStatus.keySet();
  this.isRecipientUpdate        = isRecipientUpdate;

  for (Map.Entry<SignalServiceAddress, Boolean> entry : unidentifiedStatus.entrySet()) {
    if (entry.getKey().getUuid().isPresent()) {
      unidentifiedStatusByUuid.put(entry.getKey().getUuid().get().toString(), entry.getValue());
    }
    if (entry.getKey().getNumber().isPresent()) {
      unidentifiedStatusByE164.put(entry.getKey().getNumber().get(), entry.getValue());
    }
  }
}
 
Example #3
Source Project: mollyim-android   Author: mollyim   File: GroupUtil.java    License: GNU General Public License v3.0 6 votes vote down vote up
@WorkerThread
public static void setDataMessageGroupContext(@NonNull Context context,
                                              @NonNull SignalServiceDataMessage.Builder dataMessageBuilder,
                                              @NonNull GroupId.Push groupId)
{
  if (groupId.isV2()) {
      GroupDatabase                   groupDatabase     = DatabaseFactory.getGroupDatabase(context);
      GroupDatabase.GroupRecord       groupRecord       = groupDatabase.requireGroup(groupId);
      GroupDatabase.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties();
      SignalServiceGroupV2            group             = SignalServiceGroupV2.newBuilder(v2GroupProperties.getGroupMasterKey())
                                                                              .withRevision(v2GroupProperties.getGroupRevision())
                                                                              .build();
      dataMessageBuilder.asGroupMessage(group);
    } else {
      dataMessageBuilder.asGroupMessage(new SignalServiceGroup(groupId.getDecodedId()));
    }
}
 
Example #4
Source Project: mollyim-android   Author: mollyim   File: PushSendJob.java    License: GNU General Public License v3.0 6 votes vote down vote up
protected Optional<SignalServiceDataMessage.Sticker> getStickerFor(OutgoingMediaMessage message) {
  Attachment stickerAttachment = Stream.of(message.getAttachments()).filter(Attachment::isSticker).findFirst().orElse(null);

  if (stickerAttachment == null) {
    return Optional.absent();
  }

  try {
    byte[]                  packId     = Hex.fromStringCondensed(stickerAttachment.getSticker().getPackId());
    byte[]                  packKey    = Hex.fromStringCondensed(stickerAttachment.getSticker().getPackKey());
    int                     stickerId  = stickerAttachment.getSticker().getStickerId();
    SignalServiceAttachment attachment = getAttachmentPointerFor(stickerAttachment);

    return Optional.of(new SignalServiceDataMessage.Sticker(packId, packKey, stickerId, attachment));
  } catch (IOException e) {
    Log.w(TAG, "Failed to decode sticker id/key", e);
    return Optional.absent();
  }
}
 
Example #5
Source Project: mollyim-android   Author: mollyim   File: RequestGroupInfoJob.java    License: GNU General Public License v3.0 6 votes vote down vote up
@Override
public void onRun() throws IOException, UntrustedIdentityException {
  SignalServiceGroup       group   = SignalServiceGroup.newBuilder(Type.REQUEST_INFO)
                                                       .withId(groupId.getDecodedId())
                                                       .build();

  SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder()
                                                             .asGroupMessage(group)
                                                             .withTimestamp(System.currentTimeMillis())
                                                             .build();

  SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
  Recipient                  recipient     = Recipient.resolved(source);

  messageSender.sendMessage(RecipientUtil.toSignalServiceAddress(context, recipient),
                            UnidentifiedAccessUtil.getAccessFor(context, recipient),
                            message);
}
 
Example #6
Source Project: mollyim-android   Author: mollyim   File: PushProcessMessageJob.java    License: GNU General Public License v3.0 6 votes vote down vote up
private void handleGroupV1Message(@NonNull SignalServiceContent content,
                                  @NonNull SignalServiceDataMessage message,
                                  @NonNull Optional<Long> smsMessageId,
                                  @NonNull GroupId.V1 groupId)
    throws StorageFailedException, BadGroupIdException
{
  GroupV1MessageProcessor.process(context, content, message, false);

  if (message.getExpiresInSeconds() != 0 && message.getExpiresInSeconds() != getMessageDestination(content, message).getExpireMessages()) {
    handleExpirationUpdate(content, message, Optional.absent(), Optional.of(groupId));
  }

  if (smsMessageId.isPresent()) {
    DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
  }
}
 
Example #7
Source Project: mollyim-android   Author: mollyim   File: PushProcessMessageJob.java    License: GNU General Public License v3.0 6 votes vote down vote up
private void handleReaction(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
  SignalServiceDataMessage.Reaction reaction = message.getReaction().get();

  Recipient     targetAuthor  = Recipient.externalPush(context, reaction.getTargetAuthor());
  MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(reaction.getTargetSentTimestamp(), targetAuthor.getId());

  if (targetMessage != null && !targetMessage.isRemoteDelete()) {
    Recipient         reactionAuthor = Recipient.externalPush(context, content.getSender());
    MessagingDatabase db             = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);

    if (reaction.isRemove()) {
      db.deleteReaction(targetMessage.getId(), reactionAuthor.getId());
      ApplicationDependencies.getMessageNotifier().updateNotification(context);
    } else {
      ReactionRecord reactionRecord = new ReactionRecord(reaction.getEmoji(), reactionAuthor.getId(), message.getTimestamp(), System.currentTimeMillis());
      db.addReaction(targetMessage.getId(), reactionRecord);
      ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
    }
  } else if (targetMessage != null) {
    Log.w(TAG, "[handleReaction] Found a matching message, but it's flagged as remotely deleted. timestamp: " + reaction.getTargetSentTimestamp() + "  author: " + targetAuthor.getId());
  } else {
    Log.w(TAG, "[handleReaction] Could not find matching message! timestamp: " + reaction.getTargetSentTimestamp() + "  author: " + targetAuthor.getId());
    ApplicationDependencies.getEarlyMessageCache().store(targetAuthor.getId(), reaction.getTargetSentTimestamp(), content);
  }
}
 
Example #8
Source Project: mollyim-android   Author: mollyim   File: PushProcessMessageJob.java    License: GNU General Public License v3.0 6 votes vote down vote up
private void handleRemoteDelete(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
  SignalServiceDataMessage.RemoteDelete delete = message.getRemoteDelete().get();

  Recipient     sender        = Recipient.externalPush(context, content.getSender());
  MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(delete.getTargetSentTimestamp(), sender.getId());

  if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, sender, content.getServerTimestamp())) {
    MessagingDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
    db.markAsRemoteDelete(targetMessage.getId());
    ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
  } else if (targetMessage == null) {
    Log.w(TAG, "[handleRemoteDelete] Could not find matching message! timestamp: " + delete.getTargetSentTimestamp() + "  author: " + sender.getId());
    ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), delete.getTargetSentTimestamp(), content);
  } else {
    Log.w(TAG, String.format(Locale.ENGLISH, "[handleRemoteDelete] Invalid remote delete! deleteTime: %d, targetTime: %d, deleteAuthor: %s, targetAuthor: %s",
                                              content.getServerTimestamp(), targetMessage.getServerTimestamp(), sender.getId(), targetMessage.getRecipient().getId()));
  }
}
 
Example #9
Source Project: mollyim-android   Author: mollyim   File: PointerAttachment.java    License: GNU General Public License v3.0 6 votes vote down vote up
public static Optional<Attachment> forPointer(SignalServiceDataMessage.Quote.QuotedAttachment pointer) {
  SignalServiceAttachment thumbnail = pointer.getThumbnail();

  return Optional.of(new PointerAttachment(pointer.getContentType(),
                                           AttachmentDatabase.TRANSFER_PROGRESS_PENDING,
                                           thumbnail != null ? thumbnail.asPointer().getSize().or(0) : 0,
                                           pointer.getFileName(),
                                           thumbnail != null ? thumbnail.asPointer().getCdnNumber() : 0,
                                           thumbnail != null ? thumbnail.asPointer().getRemoteId().toString() : "0",
                                           thumbnail != null && thumbnail.asPointer().getKey() != null ? Base64.encodeBytes(thumbnail.asPointer().getKey()) : null,
                                           null,
                                           thumbnail != null ? thumbnail.asPointer().getDigest().orNull() : null,
                                           null,
                                           false,
                                           thumbnail != null ? thumbnail.asPointer().getWidth() : 0,
                                           thumbnail != null ? thumbnail.asPointer().getHeight() : 0,
                                           thumbnail != null ? thumbnail.asPointer().getUploadTimestamp() : 0,
                                           thumbnail != null ? thumbnail.asPointer().getCaption().orNull() : null,
                                           null,
                                           null));
}
 
Example #10
Source Project: bcm-android   Author: bcmapp   File: PushDecryptJob.java    License: GNU General Public License v3.0 6 votes vote down vote up
private void handleEndSessionMessage(@NonNull SignalServiceProtos.Envelope envelope,
                                     @NonNull SignalServiceDataMessage message) {
    ALog.i(TAG, "handleEndSessionMessage");
    PrivateChatRepo chatRepo = repository.getChatRepo();
    IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Address.from(accountContext, envelope.getSource()),
            envelope.getSourceDevice(),
            message.getTimestamp(),
            "", Optional.absent(), 0);

    long threadId;

    IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage);
    kotlin.Pair<Long, Long> insertResult = chatRepo.insertIncomingTextMessage(incomingEndSessionMessage);

    if (insertResult.getSecond() > 0)
        threadId = insertResult.getFirst();
    else
        threadId = 0L;

    if (threadId > 0L) {
        SessionStore sessionStore = new TextSecureSessionStore(context, accountContext);
        sessionStore.deleteAllSessions(envelope.getSource());

        SecurityEvent.broadcastSecurityUpdateEvent(context);
    }
}
 
Example #11
Source Project: bcm-android   Author: bcmapp   File: PushDecryptJob.java    License: GNU General Public License v3.0 6 votes vote down vote up
private void handleExpirationUpdate(@NonNull MasterSecretUnion masterSecret,
                                    @NonNull SignalServiceProtos.Envelope envelope,
                                    @NonNull SignalServiceDataMessage message) {
    ALog.i(TAG, "handleExpirationUpdate");

    PrivateChatRepo chatRepo = repository.getChatRepo();
    Recipient recipient = getMessageDestination(envelope, message);
    IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret,
            Address.from(accountContext, envelope.getSource()),
            message.getTimestamp(), -1,
            message.getExpiresInSeconds() * 1000, true,
            Optional.fromNullable(envelope.getRelay()),
            Optional.absent(), message.getGroupInfo(),
            Optional.absent());


    chatRepo.insertIncomingMediaMessage(masterSecret.getMasterSecret().get(), mediaMessage);

    repository.getRecipientRepo().setExpireTime(recipient, message.getExpiresInSeconds());
}
 
Example #12
Source Project: bcm-android   Author: bcmapp   File: PushDecryptJob.java    License: GNU General Public License v3.0 6 votes vote down vote up
private void handleProfileKey(@NonNull SignalServiceProtos.Envelope envelope,
                              @NonNull SignalServiceDataMessage message) {
    ALog.i(TAG, "handleProfileKey");

    RecipientRepo recipientRepo = Repository.getRecipientRepo(accountContext);
    Recipient recipient = Recipient.from(accountContext, envelope.getSource(), false);

    if (recipient.getProfileKey() == null || !MessageDigest.isEqual(recipient.getProfileKey(), message.getProfileKey().get())) {
        if (recipientRepo != null) {
            recipientRepo.setProfileKey(recipient, message.getProfileKey().get());
        }

        JobManager manager = AmeModuleCenter.INSTANCE.accountJobMgr(accountContext);
        if (manager != null) {
            manager.add(new RetrieveProfileJob(context, accountContext, recipient));
        }
    }
}
 
Example #13
Source Project: signal-cli   Author: AsamK   File: Manager.java    License: GNU General Public License v3.0 6 votes vote down vote up
/**
 * This method throws an EncapsulatedExceptions exception instead of returning a list of SendMessageResult.
 */
private long sendMessageLegacy(SignalServiceDataMessage.Builder messageBuilder, Collection<SignalServiceAddress> recipients)
        throws EncapsulatedExceptions, IOException {
    final long timestamp = System.currentTimeMillis();
    messageBuilder.withTimestamp(timestamp);
    List<SendMessageResult> results = sendMessage(messageBuilder, recipients);

    List<UntrustedIdentityException> untrustedIdentities = new LinkedList<>();
    List<UnregisteredUserException> unregisteredUsers = new LinkedList<>();
    List<NetworkFailureException> networkExceptions = new LinkedList<>();

    for (SendMessageResult result : results) {
        if (result.isUnregisteredFailure()) {
            unregisteredUsers.add(new UnregisteredUserException(result.getAddress().getLegacyIdentifier(), null));
        } else if (result.isNetworkFailure()) {
            networkExceptions.add(new NetworkFailureException(result.getAddress().getLegacyIdentifier(), null));
        } else if (result.getIdentityFailure() != null) {
            untrustedIdentities.add(new UntrustedIdentityException("Untrusted", result.getAddress().getLegacyIdentifier(), result.getIdentityFailure().getIdentityKey()));
        }
    }
    if (!untrustedIdentities.isEmpty() || !unregisteredUsers.isEmpty() || !networkExceptions.isEmpty()) {
        throw new EncapsulatedExceptions(untrustedIdentities, unregisteredUsers, networkExceptions);
    }
    return timestamp;
}
 
Example #14
Source Project: signal-bot   Author: nerdclub-tfg   File: Xkcd.java    License: GNU Affero General Public License v3.0 6 votes vote down vote up
@Override
public void onMessage(User sender, Group group, SignalServiceDataMessage message) throws IOException {
	try {
		String body = stripPrefix(message.getBody().get());
		if(body.matches("\\d+")) {
			sendXkcd(sender, group, body);
		} else if(body.isEmpty()) {
			// Get newest id
			Map<String, Object> info = getData("info.0.json");
			int id = Integer.valueOf(info.get("num").toString());
			// choose a random id
			id = random.nextInt(id);
			sendXkcd(sender, group, String.valueOf(id));
		} else {
			Signal.getInstance().sendMessage(sender, group, "Usage: !xkcd [id]");
		}
	} catch(IOException e) {
		e.printStackTrace();
		Signal.getInstance().sendMessage(sender, group, "Error: " + e.getMessage());
	}
}
 
Example #15
Source Project: signal-cli   Author: AsamK   File: Manager.java    License: GNU General Public License v3.0 6 votes vote down vote up
private SendMessageResult sendSelfMessage(SignalServiceDataMessage message) throws IOException {
    SignalServiceMessageSender messageSender = getMessageSender();

    SignalServiceAddress recipient = account.getSelfAddress();

    final Optional<UnidentifiedAccessPair> unidentifiedAccess = getAccessFor(recipient);
    SentTranscriptMessage transcript = new SentTranscriptMessage(Optional.of(recipient),
            message.getTimestamp(),
            message,
            message.getExpiresInSeconds(),
            Collections.singletonMap(recipient, unidentifiedAccess.isPresent()),
            false);
    SignalServiceSyncMessage syncMessage = SignalServiceSyncMessage.forSentTranscript(transcript);

    try {
        messageSender.sendMessage(syncMessage, unidentifiedAccess);
        return SendMessageResult.success(recipient, unidentifiedAccess.isPresent(), false);
    } catch (UntrustedIdentityException e) {
        account.getSignalProtocolStore().saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), e.getIdentityKey(), TrustLevel.UNTRUSTED);
        return SendMessageResult.identityFailure(recipient, e.getIdentityKey());
    }
}
 
Example #16
Source Project: signal-bot   Author: nerdclub-tfg   File: SignalConsole.java    License: GNU Affero General Public License v3.0 6 votes vote down vote up
@Override
public void pull(int timeoutMillis) throws IOException {
	System.out.print("Enter sender: ");
	String sender = scanner.nextLine();
	System.out.println("Body:");
	String body = "";
	String line;
	while(!(line = scanner.nextLine()).isEmpty()) {
		body += line + "\n";
	}
	body = body.substring(0, body.length() - 1); // strip off last \n
	
	SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder()
			.withTimestamp(System.currentTimeMillis())
			.withBody(body)
			.build();
	for(ConversationListener listener : listeners) {
		listener.onMessage(new User(sender), message, null);
	}
}
 
Example #17
Source Project: libsignal-service-java   Author: signalapp   File: SignalServiceMessageSender.java    License: GNU General Public License v3.0 6 votes vote down vote up
/**
 * Send a message to a group.
 *
 * @param recipients The group members.
 * @param message The group message.
 * @throws IOException
 */
public List<SendMessageResult> sendMessage(List<SignalServiceAddress>             recipients,
                                           List<Optional<UnidentifiedAccessPair>> unidentifiedAccess,
                                           boolean                                isRecipientUpdate,
                                           SignalServiceDataMessage               message)
    throws IOException, UntrustedIdentityException
{
  byte[]                  content            = createMessageContent(message);
  long                    timestamp          = message.getTimestamp();
  List<SendMessageResult> results            = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false);
  boolean                 needsSyncInResults = false;

  for (SendMessageResult result : results) {
    if (result.getSuccess() != null && result.getSuccess().isNeedsSync()) {
      needsSyncInResults = true;
      break;
    }
  }

  if (needsSyncInResults || isMultiDevice.get()) {
    byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.<SignalServiceAddress>absent(), timestamp, results, isRecipientUpdate);
    sendMessage(localAddress, Optional.<UnidentifiedAccess>absent(), timestamp, syncMessage, false);
  }

  return results;
}
 
Example #18
Source Project: libsignal-service-java   Author: signalapp   File: SentTranscriptMessage.java    License: GNU General Public License v3.0 6 votes vote down vote up
public SentTranscriptMessage(Optional<SignalServiceAddress> destination, long timestamp, SignalServiceDataMessage message,
                             long expirationStartTimestamp, Map<SignalServiceAddress, Boolean> unidentifiedStatus,
                             boolean isRecipientUpdate)
{
  this.destination              = destination;
  this.timestamp                = timestamp;
  this.message                  = message;
  this.expirationStartTimestamp = expirationStartTimestamp;
  this.unidentifiedStatusByUuid = new HashMap<>();
  this.unidentifiedStatusByE164 = new HashMap<>();
  this.recipients               = unidentifiedStatus.keySet();
  this.isRecipientUpdate        = isRecipientUpdate;

  for (Map.Entry<SignalServiceAddress, Boolean> entry : unidentifiedStatus.entrySet()) {
    if (entry.getKey().getUuid().isPresent()) {
      unidentifiedStatusByUuid.put(entry.getKey().getUuid().get().toString(), entry.getValue());
    }
    if (entry.getKey().getNumber().isPresent()) {
      unidentifiedStatusByE164.put(entry.getKey().getNumber().get(), entry.getValue());
    }
  }
}
 
Example #19
Source Project: libsignal-service-java   Author: signalapp   File: SignalServiceCipher.java    License: GNU General Public License v3.0 6 votes vote down vote up
private SignalServiceDataMessage.Quote createQuote(DataMessage content) {
  if (!content.hasQuote()) return null;

  List<SignalServiceDataMessage.Quote.QuotedAttachment> attachments = new LinkedList<>();

  for (DataMessage.Quote.QuotedAttachment attachment : content.getQuote().getAttachmentsList()) {
    attachments.add(new SignalServiceDataMessage.Quote.QuotedAttachment(attachment.getContentType(),
                                                                        attachment.getFileName(),
                                                                        attachment.hasThumbnail() ? createAttachmentPointer(attachment.getThumbnail()) : null));
  }

  if (SignalServiceAddress.isValidAddress(content.getQuote().getAuthorUuid(), content.getQuote().getAuthorE164())) {
    SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parseOrNull(content.getQuote().getAuthorUuid()), content.getQuote().getAuthorE164());

    return new SignalServiceDataMessage.Quote(content.getQuote().getId(),
                                              address,
                                              content.getQuote().getText(),
                                              attachments);
  } else {
    Log.w(TAG, "Quote was missing an author! Returning null.");
    return null;
  }
}
 
Example #20
Source Project: signal-cli   Author: AsamK   File: Manager.java    License: GNU General Public License v3.0 6 votes vote down vote up
public long sendGroupMessage(String messageText, List<String> attachments,
                             byte[] groupId)
        throws IOException, EncapsulatedExceptions, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException {
    final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder().withBody(messageText);
    if (attachments != null) {
        messageBuilder.withAttachments(Utils.getSignalServiceAttachments(attachments));
    }
    if (groupId != null) {
        SignalServiceGroup group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.DELIVER)
                .withId(groupId)
                .build();
        messageBuilder.asGroupMessage(group);
    }

    final GroupInfo g = getGroupForSending(groupId);

    messageBuilder.withExpiration(g.messageExpirationTime);

    return sendMessageLegacy(messageBuilder, g.getMembersWithout(account.getSelfAddress()));
}
 
Example #21
Source Project: signal-cli   Author: AsamK   File: Manager.java    License: GNU General Public License v3.0 6 votes vote down vote up
private SignalServiceDataMessage.Builder getGroupUpdateMessageBuilder(GroupInfo g) throws AttachmentInvalidException {
    SignalServiceGroup.Builder group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.UPDATE)
            .withId(g.groupId)
            .withName(g.name)
            .withMembers(new ArrayList<>(g.getMembers()));

    File aFile = getGroupAvatarFile(g.groupId);
    if (aFile.exists()) {
        try {
            group.withAvatar(Utils.createAttachment(aFile));
        } catch (IOException e) {
            throw new AttachmentInvalidException(aFile.toString(), e);
        }
    }

    return SignalServiceDataMessage.newBuilder()
            .asGroupMessage(group.build())
            .withExpiration(g.messageExpirationTime);
}
 
Example #22
Source Project: signal-cli   Author: AsamK   File: JsonDataMessage.java    License: GNU General Public License v3.0 6 votes vote down vote up
JsonDataMessage(SignalServiceDataMessage dataMessage) {
    this.timestamp = dataMessage.getTimestamp();
    if (dataMessage.getGroupContext().isPresent() && dataMessage.getGroupContext().get().getGroupV1().isPresent()) {
        SignalServiceGroup groupInfo = dataMessage.getGroupContext().get().getGroupV1().get();
        this.groupInfo = new JsonGroupInfo(groupInfo);
    }
    if (dataMessage.getBody().isPresent()) {
        this.message = dataMessage.getBody().get();
    }
    this.expiresInSeconds = dataMessage.getExpiresInSeconds();
    if (dataMessage.getAttachments().isPresent()) {
        this.attachments = new ArrayList<>(dataMessage.getAttachments().get().size());
        for (SignalServiceAttachment attachment : dataMessage.getAttachments().get()) {
            this.attachments.add(new JsonAttachment(attachment));
        }
    } else {
        this.attachments = new ArrayList<>();
    }
}
 
Example #23
Source Project: signal-cli   Author: AsamK   File: Manager.java    License: GNU General Public License v3.0 6 votes vote down vote up
private boolean isMessageBlocked(SignalServiceEnvelope envelope, SignalServiceContent content) {
    SignalServiceAddress source;
    if (!envelope.isUnidentifiedSender() && envelope.hasSource()) {
        source = envelope.getSourceAddress();
    } else if (content != null) {
        source = content.getSender();
    } else {
        return false;
    }
    ContactInfo sourceContact = account.getContactStore().getContact(source);
    if (sourceContact != null && sourceContact.blocked) {
        return true;
    }

    if (content != null && content.getDataMessage().isPresent()) {
        SignalServiceDataMessage message = content.getDataMessage().get();
        if (message.getGroupContext().isPresent() && message.getGroupContext().get().getGroupV1().isPresent()) {
            SignalServiceGroup groupInfo = message.getGroupContext().get().getGroupV1().get();
            GroupInfo group = getGroup(groupInfo.getGroupId());
            if (groupInfo.getType() == SignalServiceGroup.Type.DELIVER && group != null && group.blocked) {
                return true;
            }
        }
    }
    return false;
}
 
Example #24
Source Project: mollyim-android   Author: mollyim   File: SignalServiceMessageSender.java    License: GNU General Public License v3.0 5 votes vote down vote up
/**
 * Send a message to a single recipient.
 *
 * @param recipient The message's destination.
 * @param message The message.
 * @throws UntrustedIdentityException
 * @throws IOException
 */
public SendMessageResult sendMessage(SignalServiceAddress             recipient,
                                     Optional<UnidentifiedAccessPair> unidentifiedAccess,
                                     SignalServiceDataMessage         message)
    throws UntrustedIdentityException, IOException
{
  byte[]            content   = createMessageContent(message);
  long              timestamp = message.getTimestamp();
  SendMessageResult result    = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false);

  if (result.getSuccess() != null && result.getSuccess().isNeedsSync()) {
    byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false);
    sendMessage(localAddress, Optional.<UnidentifiedAccess>absent(), timestamp, syncMessage, false);
  }

  if (message.isEndSession()) {
    if (recipient.getUuid().isPresent()) {
      store.deleteAllSessions(recipient.getUuid().get().toString());
    }
    if (recipient.getNumber().isPresent()) {
      store.deleteAllSessions(recipient.getNumber().get());
    }

    if (eventListener.isPresent()) {
      eventListener.get().onSecurityEvent(recipient);
    }
  }

  return result;
}
 
Example #25
Source Project: mollyim-android   Author: mollyim   File: GroupV1MessageProcessor.java    License: GNU General Public License v3.0 5 votes vote down vote up
public static @Nullable Long process(@NonNull Context context,
                                     @NonNull SignalServiceContent content,
                                     @NonNull SignalServiceDataMessage message,
                                     boolean outgoing)
{
  SignalServiceGroupContext    signalServiceGroupContext = message.getGroupContext().get();
  Optional<SignalServiceGroup> groupV1                   = signalServiceGroupContext.getGroupV1();

  if (signalServiceGroupContext.getGroupV2().isPresent()) {
    throw new AssertionError("Cannot process GV2");
  }

  if (!groupV1.isPresent() || groupV1.get().getGroupId() == null) {
    Log.w(TAG, "Received group message with no id! Ignoring...");
    return null;
  }

  GroupDatabase         database = DatabaseFactory.getGroupDatabase(context);
  SignalServiceGroup    group    = groupV1.get();
  GroupId               id       = GroupId.v1orThrow(group.getGroupId());
  Optional<GroupRecord> record   = database.getGroup(id);

  if (record.isPresent() && group.getType() == Type.UPDATE) {
    return handleGroupUpdate(context, content, group, record.get(), outgoing);
  } else if (!record.isPresent() && group.getType() == Type.UPDATE) {
    return handleGroupCreate(context, content, group, outgoing);
  } else if (record.isPresent() && group.getType() == Type.QUIT) {
    return handleGroupLeave(context, content, group, record.get(), outgoing);
  } else if (record.isPresent() && group.getType() == Type.REQUEST_INFO) {
    return handleGroupInfoRequest(context, content, record.get());
  } else {
    Log.w(TAG, "Received unknown type, ignoring...");
    return null;
  }
}
 
Example #26
Source Project: mollyim-android   Author: mollyim   File: PushSendJob.java    License: GNU General Public License v3.0 5 votes vote down vote up
protected SignalServiceSyncMessage buildSelfSendSyncMessage(@NonNull Context context, @NonNull SignalServiceDataMessage message, Optional<UnidentifiedAccessPair> syncAccess) {
  SignalServiceAddress  localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalUuid(context), TextSecurePreferences.getLocalNumber(context));
  SentTranscriptMessage transcript   = new SentTranscriptMessage(Optional.of(localAddress),
                                                                 message.getTimestamp(),
                                                                 message,
                                                                 message.getExpiresInSeconds(),
                                                                 Collections.singletonMap(localAddress, syncAccess.isPresent()),
                                                                 false);
  return SignalServiceSyncMessage.forSentTranscript(transcript);
}
 
Example #27
Source Project: mollyim-android   Author: mollyim   File: LeaveGroupJob.java    License: GNU General Public License v3.0 5 votes vote down vote up
private static @NonNull List<Recipient> deliver(@NonNull Context context,
                                                @NonNull GroupId.Push groupId,
                                                @NonNull String name,
                                                @NonNull List<RecipientId> members,
                                                @NonNull List<RecipientId> destinations)
    throws IOException, UntrustedIdentityException
{
  SignalServiceMessageSender             messageSender      = ApplicationDependencies.getSignalServiceMessageSender();
  List<SignalServiceAddress>             addresses          = Stream.of(destinations).map(Recipient::resolved).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
  List<SignalServiceAddress>             memberAddresses    = Stream.of(members).map(Recipient::resolved).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
  List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(destinations).map(Recipient::resolved).map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)).toList();
  SignalServiceGroup                     serviceGroup       = new SignalServiceGroup(SignalServiceGroup.Type.QUIT, groupId.getDecodedId(), name, memberAddresses, null);
  SignalServiceDataMessage.Builder       dataMessage        = SignalServiceDataMessage.newBuilder()
                                                                                      .withTimestamp(System.currentTimeMillis())
                                                                                      .asGroupMessage(serviceGroup);


  List<SendMessageResult> results = messageSender.sendMessage(addresses, unidentifiedAccess, false, dataMessage.build());

  Stream.of(results)
        .filter(r -> r.getIdentityFailure() != null)
        .map(SendMessageResult::getAddress)
        .map(a -> Recipient.externalPush(context, a))
        .forEach(r -> Log.w(TAG, "Identity failure for " + r.getId()));

  Stream.of(results)
        .filter(SendMessageResult::isUnregisteredFailure)
        .map(SendMessageResult::getAddress)
        .map(a -> Recipient.externalPush(context, a))
        .forEach(r -> Log.w(TAG, "Unregistered failure for " + r.getId()));


  return Stream.of(results)
               .filter(r -> r.getSuccess() != null || r.getIdentityFailure() != null || r.isUnregisteredFailure())
               .map(SendMessageResult::getAddress)
               .map(a -> Recipient.externalPush(context, a))
               .toList();
}
 
Example #28
Source Project: mollyim-android   Author: mollyim   File: ProfileKeySendJob.java    License: GNU General Public License v3.0 5 votes vote down vote up
private List<Recipient> deliver(@NonNull Recipient conversationRecipient, @NonNull List<Recipient> destinations) throws IOException, UntrustedIdentityException {
  SignalServiceMessageSender             messageSender      = ApplicationDependencies.getSignalServiceMessageSender();
  List<SignalServiceAddress>             addresses          = Stream.of(destinations).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
  List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(destinations).map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)).toList();
  SignalServiceDataMessage.Builder       dataMessage        = SignalServiceDataMessage.newBuilder()
                                                                                      .asProfileKeyUpdate(true)
                                                                                      .withTimestamp(System.currentTimeMillis())
                                                                                      .withProfileKey(Recipient.self().resolve().getProfileKey());

  if (conversationRecipient.isGroup()) {
    dataMessage.asGroupMessage(new SignalServiceGroup(conversationRecipient.requireGroupId().getDecodedId()));
  }

  List<SendMessageResult> results = messageSender.sendMessage(addresses, unidentifiedAccess, false, dataMessage.build());

  Stream.of(results)
        .filter(r -> r.getIdentityFailure() != null)
        .map(SendMessageResult::getAddress)
        .map(a -> Recipient.externalPush(context, a))
        .forEach(r -> Log.w(TAG, "Identity failure for " + r.getId()));

  Stream.of(results)
        .filter(SendMessageResult::isUnregisteredFailure)
        .map(SendMessageResult::getAddress)
        .map(a -> Recipient.externalPush(context, a))
        .forEach(r -> Log.w(TAG, "Unregistered failure for " + r.getId()));


  return Stream.of(results)
               .filter(r -> r.getSuccess() != null || r.getIdentityFailure() != null || r.isUnregisteredFailure())
               .map(SendMessageResult::getAddress)
               .map(a -> Recipient.externalPush(context, a))
               .toList();
}
 
Example #29
Source Project: mollyim-android   Author: mollyim   File: ReactionSendJob.java    License: GNU General Public License v3.0 5 votes vote down vote up
private @NonNull List<Recipient> deliver(@NonNull Recipient conversationRecipient, @NonNull List<Recipient> destinations, @NonNull Recipient targetAuthor, long targetSentTimestamp)
    throws IOException, UntrustedIdentityException
{
  SignalServiceMessageSender             messageSender      = ApplicationDependencies.getSignalServiceMessageSender();
  List<SignalServiceAddress>             addresses          = Stream.of(destinations).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
  List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(destinations).map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)).toList();
  SignalServiceDataMessage.Builder       dataMessage        = SignalServiceDataMessage.newBuilder()
                                                                                      .withTimestamp(System.currentTimeMillis())
                                                                                      .withReaction(buildReaction(context, reaction, remove, targetAuthor, targetSentTimestamp));

  if (conversationRecipient.isGroup()) {
    GroupUtil.setDataMessageGroupContext(context, dataMessage, conversationRecipient.requireGroupId().requirePush());
  }


  List<SendMessageResult> results = messageSender.sendMessage(addresses, unidentifiedAccess, false, dataMessage.build());

  Stream.of(results)
        .filter(r -> r.getIdentityFailure() != null)
        .map(SendMessageResult::getAddress)
        .map(a -> Recipient.externalPush(context, a))
        .forEach(r -> Log.w(TAG, "Identity failure for " + r.getId()));

  Stream.of(results)
        .filter(SendMessageResult::isUnregisteredFailure)
        .map(SendMessageResult::getAddress)
        .map(a -> Recipient.externalPush(context, a))
        .forEach(r -> Log.w(TAG, "Unregistered failure for " + r.getId()));


  return Stream.of(results)
               .filter(r -> r.getSuccess() != null || r.getIdentityFailure() != null || r.isUnregisteredFailure())
               .map(SendMessageResult::getAddress)
               .map(a -> Recipient.externalPush(context, a))
               .toList();
}
 
Example #30
Source Project: mollyim-android   Author: mollyim   File: ReactionSendJob.java    License: GNU General Public License v3.0 5 votes vote down vote up
private static SignalServiceDataMessage.Reaction buildReaction(@NonNull Context context,
                                                               @NonNull ReactionRecord reaction,
                                                               boolean remove,
                                                               @NonNull Recipient targetAuthor,
                                                               long targetSentTimestamp)
{
  return new SignalServiceDataMessage.Reaction(reaction.getEmoji(),
                                               remove,
                                               RecipientUtil.toSignalServiceAddress(context, targetAuthor),
                                               targetSentTimestamp);
}