Search in sources :

Example 1 with SharedContact

use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.

the class SignalServiceMessageSender method createSharedContactContent.

private List<DataMessage.Contact> createSharedContactContent(List<SharedContact> contacts) throws IOException {
    List<DataMessage.Contact> results = new LinkedList<>();
    for (SharedContact contact : contacts) {
        DataMessage.Contact.Name.Builder nameBuilder = DataMessage.Contact.Name.newBuilder();
        if (contact.getName().getFamily().isPresent())
            nameBuilder.setFamilyName(contact.getName().getFamily().get());
        if (contact.getName().getGiven().isPresent())
            nameBuilder.setGivenName(contact.getName().getGiven().get());
        if (contact.getName().getMiddle().isPresent())
            nameBuilder.setMiddleName(contact.getName().getMiddle().get());
        if (contact.getName().getPrefix().isPresent())
            nameBuilder.setPrefix(contact.getName().getPrefix().get());
        if (contact.getName().getSuffix().isPresent())
            nameBuilder.setSuffix(contact.getName().getSuffix().get());
        if (contact.getName().getDisplay().isPresent())
            nameBuilder.setDisplayName(contact.getName().getDisplay().get());
        DataMessage.Contact.Builder contactBuilder = DataMessage.Contact.newBuilder().setName(nameBuilder);
        if (contact.getAddress().isPresent()) {
            for (SharedContact.PostalAddress address : contact.getAddress().get()) {
                DataMessage.Contact.PostalAddress.Builder addressBuilder = DataMessage.Contact.PostalAddress.newBuilder();
                switch(address.getType()) {
                    case HOME:
                        addressBuilder.setType(DataMessage.Contact.PostalAddress.Type.HOME);
                        break;
                    case WORK:
                        addressBuilder.setType(DataMessage.Contact.PostalAddress.Type.WORK);
                        break;
                    case CUSTOM:
                        addressBuilder.setType(DataMessage.Contact.PostalAddress.Type.CUSTOM);
                        break;
                    default:
                        throw new AssertionError("Unknown type: " + address.getType());
                }
                if (address.getCity().isPresent())
                    addressBuilder.setCity(address.getCity().get());
                if (address.getCountry().isPresent())
                    addressBuilder.setCountry(address.getCountry().get());
                if (address.getLabel().isPresent())
                    addressBuilder.setLabel(address.getLabel().get());
                if (address.getNeighborhood().isPresent())
                    addressBuilder.setNeighborhood(address.getNeighborhood().get());
                if (address.getPobox().isPresent())
                    addressBuilder.setPobox(address.getPobox().get());
                if (address.getPostcode().isPresent())
                    addressBuilder.setPostcode(address.getPostcode().get());
                if (address.getRegion().isPresent())
                    addressBuilder.setRegion(address.getRegion().get());
                if (address.getStreet().isPresent())
                    addressBuilder.setStreet(address.getStreet().get());
                contactBuilder.addAddress(addressBuilder);
            }
        }
        if (contact.getEmail().isPresent()) {
            for (SharedContact.Email email : contact.getEmail().get()) {
                DataMessage.Contact.Email.Builder emailBuilder = DataMessage.Contact.Email.newBuilder().setValue(email.getValue());
                switch(email.getType()) {
                    case HOME:
                        emailBuilder.setType(DataMessage.Contact.Email.Type.HOME);
                        break;
                    case WORK:
                        emailBuilder.setType(DataMessage.Contact.Email.Type.WORK);
                        break;
                    case MOBILE:
                        emailBuilder.setType(DataMessage.Contact.Email.Type.MOBILE);
                        break;
                    case CUSTOM:
                        emailBuilder.setType(DataMessage.Contact.Email.Type.CUSTOM);
                        break;
                    default:
                        throw new AssertionError("Unknown type: " + email.getType());
                }
                if (email.getLabel().isPresent())
                    emailBuilder.setLabel(email.getLabel().get());
                contactBuilder.addEmail(emailBuilder);
            }
        }
        if (contact.getPhone().isPresent()) {
            for (SharedContact.Phone phone : contact.getPhone().get()) {
                DataMessage.Contact.Phone.Builder phoneBuilder = DataMessage.Contact.Phone.newBuilder().setValue(phone.getValue());
                switch(phone.getType()) {
                    case HOME:
                        phoneBuilder.setType(DataMessage.Contact.Phone.Type.HOME);
                        break;
                    case WORK:
                        phoneBuilder.setType(DataMessage.Contact.Phone.Type.WORK);
                        break;
                    case MOBILE:
                        phoneBuilder.setType(DataMessage.Contact.Phone.Type.MOBILE);
                        break;
                    case CUSTOM:
                        phoneBuilder.setType(DataMessage.Contact.Phone.Type.CUSTOM);
                        break;
                    default:
                        throw new AssertionError("Unknown type: " + phone.getType());
                }
                if (phone.getLabel().isPresent())
                    phoneBuilder.setLabel(phone.getLabel().get());
                contactBuilder.addNumber(phoneBuilder);
            }
        }
        if (contact.getAvatar().isPresent()) {
            AttachmentPointer pointer = contact.getAvatar().get().getAttachment().isStream() ? createAttachmentPointer(contact.getAvatar().get().getAttachment().asStream()) : createAttachmentPointer(contact.getAvatar().get().getAttachment().asPointer());
            contactBuilder.setAvatar(DataMessage.Contact.Avatar.newBuilder().setAvatar(pointer).setIsProfile(contact.getAvatar().get().isProfile()));
        }
        if (contact.getOrganization().isPresent()) {
            contactBuilder.setOrganization(contact.getOrganization().get());
        }
        results.add(contactBuilder.build());
    }
    return results;
}
Also used : LinkedList(java.util.LinkedList) SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact) DataMessage(org.whispersystems.signalservice.internal.push.SignalServiceProtos.DataMessage) SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact) AttachmentPointer(org.whispersystems.signalservice.internal.push.SignalServiceProtos.AttachmentPointer) SignalServiceAttachmentPointer(org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer)

Example 2 with SharedContact

use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.

the class SignalServiceContent method createSignalServiceMessage.

private static SignalServiceDataMessage createSignalServiceMessage(SignalServiceMetadata metadata, SignalServiceProtos.DataMessage content) throws UnsupportedDataMessageException, InvalidMessageStructureException {
    SignalServiceGroupV2 groupInfoV2 = createGroupV2Info(content);
    Optional<SignalServiceGroupContext> groupContext;
    try {
        groupContext = SignalServiceGroupContext.createOptional(null, groupInfoV2);
    } catch (InvalidMessageException e) {
        throw new InvalidMessageStructureException(e);
    }
    List<SignalServiceAttachment> attachments = new LinkedList<>();
    boolean endSession = ((content.getFlags() & SignalServiceProtos.DataMessage.Flags.END_SESSION_VALUE) != 0);
    boolean expirationUpdate = ((content.getFlags() & SignalServiceProtos.DataMessage.Flags.EXPIRATION_TIMER_UPDATE_VALUE) != 0);
    boolean profileKeyUpdate = ((content.getFlags() & SignalServiceProtos.DataMessage.Flags.PROFILE_KEY_UPDATE_VALUE) != 0);
    boolean isGroupV2 = groupInfoV2 != null;
    SignalServiceDataMessage.Quote quote = createQuote(content, isGroupV2);
    List<SharedContact> sharedContacts = createSharedContacts(content);
    List<SignalServiceDataMessage.Preview> previews = createPreviews(content);
    List<SignalServiceDataMessage.Mention> mentions = createMentions(content.getBodyRangesList(), content.getBody(), isGroupV2);
    SignalServiceDataMessage.Sticker sticker = createSticker(content);
    SignalServiceDataMessage.Reaction reaction = createReaction(content);
    SignalServiceDataMessage.RemoteDelete remoteDelete = createRemoteDelete(content);
    SignalServiceDataMessage.GroupCallUpdate groupCallUpdate = createGroupCallUpdate(content);
    SignalServiceDataMessage.StoryContext storyContext = createStoryContext(content);
    if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT_VALUE) {
        throw new UnsupportedDataMessageProtocolVersionException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT_VALUE, content.getRequiredProtocolVersion(), metadata.getSender().getIdentifier(), metadata.getSenderDevice(), groupContext);
    }
    SignalServiceDataMessage.Payment payment = createPayment(content);
    if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber()) {
        throw new UnsupportedDataMessageProtocolVersionException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber(), content.getRequiredProtocolVersion(), metadata.getSender().getIdentifier(), metadata.getSenderDevice(), groupContext);
    }
    for (SignalServiceProtos.AttachmentPointer pointer : content.getAttachmentsList()) {
        attachments.add(createAttachmentPointer(pointer));
    }
    if (content.hasTimestamp() && content.getTimestamp() != metadata.getTimestamp()) {
        throw new InvalidMessageStructureException("Timestamps don't match: " + content.getTimestamp() + " vs " + metadata.getTimestamp(), metadata.getSender().getIdentifier(), metadata.getSenderDevice());
    }
    return new SignalServiceDataMessage(metadata.getTimestamp(), null, groupInfoV2, attachments, content.hasBody() ? content.getBody() : null, endSession, content.getExpireTimer(), expirationUpdate, content.hasProfileKey() ? content.getProfileKey().toByteArray() : null, profileKeyUpdate, quote, sharedContacts, previews, mentions, sticker, content.getIsViewOnce(), reaction, remoteDelete, groupCallUpdate, payment, storyContext);
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) ProtocolInvalidMessageException(org.signal.libsignal.metadata.ProtocolInvalidMessageException) InvalidMessageStructureException(org.whispersystems.signalservice.api.InvalidMessageStructureException) LinkedList(java.util.LinkedList) UnsupportedDataMessageProtocolVersionException(org.whispersystems.signalservice.internal.push.UnsupportedDataMessageProtocolVersionException) SignalServiceProtos(org.whispersystems.signalservice.internal.push.SignalServiceProtos) SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact)

Example 3 with SharedContact

use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.

the class ContactModelMapper method remoteToLocal.

public static Contact remoteToLocal(@NonNull SharedContact sharedContact) {
    Name name = new Name(sharedContact.getName().getDisplay().orNull(), sharedContact.getName().getGiven().orNull(), sharedContact.getName().getFamily().orNull(), sharedContact.getName().getPrefix().orNull(), sharedContact.getName().getSuffix().orNull(), sharedContact.getName().getMiddle().orNull());
    List<Phone> phoneNumbers = new LinkedList<>();
    if (sharedContact.getPhone().isPresent()) {
        for (SharedContact.Phone phone : sharedContact.getPhone().get()) {
            phoneNumbers.add(new Phone(phone.getValue(), remoteToLocalType(phone.getType()), phone.getLabel().orNull()));
        }
    }
    List<Email> emails = new LinkedList<>();
    if (sharedContact.getEmail().isPresent()) {
        for (SharedContact.Email email : sharedContact.getEmail().get()) {
            emails.add(new Email(email.getValue(), remoteToLocalType(email.getType()), email.getLabel().orNull()));
        }
    }
    List<PostalAddress> postalAddresses = new LinkedList<>();
    if (sharedContact.getAddress().isPresent()) {
        for (SharedContact.PostalAddress postalAddress : sharedContact.getAddress().get()) {
            postalAddresses.add(new PostalAddress(remoteToLocalType(postalAddress.getType()), postalAddress.getLabel().orNull(), postalAddress.getStreet().orNull(), postalAddress.getPobox().orNull(), postalAddress.getNeighborhood().orNull(), postalAddress.getCity().orNull(), postalAddress.getRegion().orNull(), postalAddress.getPostcode().orNull(), postalAddress.getCountry().orNull()));
        }
    }
    Avatar avatar = null;
    if (sharedContact.getAvatar().isPresent()) {
        Attachment attachment = PointerAttachment.forPointer(Optional.of(sharedContact.getAvatar().get().getAttachment().asPointer())).get();
        boolean isProfile = sharedContact.getAvatar().get().isProfile();
        avatar = new Avatar(null, attachment, isProfile);
    }
    return new Contact(name, sharedContact.getOrganization().orNull(), phoneNumbers, emails, postalAddresses, avatar);
}
Also used : Email(org.thoughtcrime.securesms.contactshare.Contact.Email) PointerAttachment(org.thoughtcrime.securesms.attachments.PointerAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) LinkedList(java.util.LinkedList) Avatar(org.thoughtcrime.securesms.contactshare.Contact.Avatar) Name(org.thoughtcrime.securesms.contactshare.Contact.Name) SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact) PostalAddress(org.thoughtcrime.securesms.contactshare.Contact.PostalAddress) Phone(org.thoughtcrime.securesms.contactshare.Contact.Phone) SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact)

Example 4 with SharedContact

use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.

the class PushSendJob method getSharedContactsFor.

List<SharedContact> getSharedContactsFor(OutgoingMediaMessage mediaMessage) {
    List<SharedContact> sharedContacts = new LinkedList<>();
    for (Contact contact : mediaMessage.getSharedContacts()) {
        SharedContact.Builder builder = ContactModelMapper.localToRemoteBuilder(contact);
        SharedContact.Avatar avatar = null;
        if (contact.getAvatar() != null && contact.getAvatar().getAttachment() != null) {
            avatar = SharedContact.Avatar.newBuilder().withAttachment(getAttachmentFor(contact.getAvatarAttachment())).withProfileFlag(contact.getAvatar().isProfile()).build();
        }
        builder.setAvatar(avatar);
        sharedContacts.add(builder.build());
    }
    return sharedContacts;
}
Also used : SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact) LinkedList(java.util.LinkedList) SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact) Contact(org.thoughtcrime.securesms.contactshare.Contact)

Example 5 with SharedContact

use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.

the class PushGroupSendJob method deliver.

private List<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull Recipient groupRecipient, @NonNull List<Recipient> destinations) throws IOException, UntrustedIdentityException, UndeliverableMessageException {
    try {
        rotateSenderCertificateIfNecessary();
        GroupId.Push groupId = groupRecipient.requireGroupId().requirePush();
        Optional<byte[]> profileKey = getProfileKey(groupRecipient);
        Optional<Quote> quote = getQuoteFor(message);
        Optional<SignalServiceDataMessage.Sticker> sticker = getStickerFor(message);
        List<SharedContact> sharedContacts = getSharedContactsFor(message);
        List<Preview> previews = getPreviewsFor(message);
        List<SignalServiceDataMessage.Mention> mentions = getMentionsFor(message.getMentions());
        List<Attachment> attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList();
        List<SignalServiceAttachment> attachmentPointers = getAttachmentPointersFor(attachments);
        boolean isRecipientUpdate = Stream.of(SignalDatabase.groupReceipts().getGroupReceiptInfo(messageId)).anyMatch(info -> info.getStatus() > GroupReceiptDatabase.STATUS_UNDELIVERED);
        if (message.isGroup()) {
            OutgoingGroupUpdateMessage groupMessage = (OutgoingGroupUpdateMessage) message;
            if (groupMessage.isV2Group()) {
                MessageGroupContext.GroupV2Properties properties = groupMessage.requireGroupV2Properties();
                GroupContextV2 groupContext = properties.getGroupContext();
                SignalServiceGroupV2.Builder builder = SignalServiceGroupV2.newBuilder(properties.getGroupMasterKey()).withRevision(groupContext.getRevision());
                ByteString groupChange = groupContext.getGroupChange();
                if (groupChange != null) {
                    builder.withSignedGroupChange(groupChange.toByteArray());
                }
                SignalServiceGroupV2 group = builder.build();
                SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder().withTimestamp(message.getSentTimeMillis()).withExpiration(groupRecipient.getExpiresInSeconds()).asGroupMessage(group).build();
                return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage);
            } else {
                throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
            }
        } else {
            Optional<GroupDatabase.GroupRecord> groupRecord = SignalDatabase.groups().getGroup(groupRecipient.requireGroupId());
            if (groupRecord.isPresent() && groupRecord.get().isAnnouncementGroup() && !groupRecord.get().isAdmin(Recipient.self())) {
                throw new UndeliverableMessageException("Non-admins cannot send messages in announcement groups!");
            }
            SignalServiceDataMessage.Builder builder = SignalServiceDataMessage.newBuilder().withTimestamp(message.getSentTimeMillis());
            GroupUtil.setDataMessageGroupContext(context, builder, groupId);
            SignalServiceDataMessage groupMessage = builder.withAttachments(attachmentPointers).withBody(message.getBody()).withExpiration((int) (message.getExpiresIn() / 1000)).withViewOnce(message.isViewOnce()).asExpirationUpdate(message.isExpirationUpdate()).withProfileKey(profileKey.orNull()).withQuote(quote.orNull()).withSticker(sticker.orNull()).withSharedContacts(sharedContacts).withPreviews(previews).withMentions(mentions).build();
            Log.i(TAG, JobLogger.format(this, "Beginning message send."));
            return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.getGroupId().transform(GroupId::requireV2).orNull(), destinations, isRecipientUpdate, ContentHint.RESENDABLE, new MessageId(messageId, true), groupMessage);
        }
    } catch (ServerRejectedException e) {
        throw new UndeliverableMessageException(e);
    }
}
Also used : ByteString(com.google.protobuf.ByteString) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) OutgoingGroupUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage) GroupContextV2(org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2) MessageGroupContext(org.thoughtcrime.securesms.mms.MessageGroupContext) UndeliverableMessageException(org.thoughtcrime.securesms.transport.UndeliverableMessageException) Preview(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview) ServerRejectedException(org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException) SignalServiceGroupV2(org.whispersystems.signalservice.api.messages.SignalServiceGroupV2) GroupId(org.thoughtcrime.securesms.groups.GroupId) Quote(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Quote) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact) MessageId(org.thoughtcrime.securesms.database.model.MessageId)

Aggregations

SharedContact (org.whispersystems.signalservice.api.messages.shared.SharedContact)6 LinkedList (java.util.LinkedList)4 Attachment (org.thoughtcrime.securesms.attachments.Attachment)3 SignalServiceDataMessage (org.whispersystems.signalservice.api.messages.SignalServiceDataMessage)3 MessageId (org.thoughtcrime.securesms.database.model.MessageId)2 UndeliverableMessageException (org.thoughtcrime.securesms.transport.UndeliverableMessageException)2 SignalServiceAttachment (org.whispersystems.signalservice.api.messages.SignalServiceAttachment)2 Preview (org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview)2 ServerRejectedException (org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException)2 ByteString (com.google.protobuf.ByteString)1 FileNotFoundException (java.io.FileNotFoundException)1 ProtocolInvalidMessageException (org.signal.libsignal.metadata.ProtocolInvalidMessageException)1 PointerAttachment (org.thoughtcrime.securesms.attachments.PointerAttachment)1 Contact (org.thoughtcrime.securesms.contactshare.Contact)1 Avatar (org.thoughtcrime.securesms.contactshare.Contact.Avatar)1 Email (org.thoughtcrime.securesms.contactshare.Contact.Email)1 Name (org.thoughtcrime.securesms.contactshare.Contact.Name)1 Phone (org.thoughtcrime.securesms.contactshare.Contact.Phone)1 PostalAddress (org.thoughtcrime.securesms.contactshare.Contact.PostalAddress)1 SyncMessageId (org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId)1