use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project Signal-Android by WhisperSystems.
the class PushMediaSendJob method deliver.
private boolean deliver(OutgoingMediaMessage message) throws IOException, InsecureFallbackApprovalException, UntrustedIdentityException, UndeliverableMessageException {
if (message.getRecipient() == null) {
throw new UndeliverableMessageException("No destination address.");
}
try {
rotateSenderCertificateIfNecessary();
Recipient messageRecipient = message.getRecipient().fresh();
if (messageRecipient.isUnregistered()) {
throw new UndeliverableMessageException(messageRecipient.getId() + " not registered!");
}
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, messageRecipient);
List<Attachment> attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList();
List<SignalServiceAttachment> serviceAttachments = getAttachmentPointersFor(attachments);
Optional<byte[]> profileKey = getProfileKey(messageRecipient);
Optional<SignalServiceDataMessage.Quote> quote = getQuoteFor(message);
Optional<SignalServiceDataMessage.Sticker> sticker = getStickerFor(message);
List<SharedContact> sharedContacts = getSharedContactsFor(message);
List<Preview> previews = getPreviewsFor(message);
SignalServiceDataMessage mediaMessage = SignalServiceDataMessage.newBuilder().withBody(message.getBody()).withAttachments(serviceAttachments).withTimestamp(message.getSentTimeMillis()).withExpiration((int) (message.getExpiresIn() / 1000)).withViewOnce(message.isViewOnce()).withProfileKey(profileKey.orNull()).withQuote(quote.orNull()).withSticker(sticker.orNull()).withSharedContacts(sharedContacts).withPreviews(previews).asExpirationUpdate(message.isExpirationUpdate()).build();
if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) {
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SendMessageResult result = messageSender.sendSyncMessage(mediaMessage);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
return syncAccess.isPresent();
} else {
SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage, IndividualSendEvents.EMPTY);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
return result.getSuccess().isUnidentified();
}
} catch (UnregisteredUserException e) {
warn(TAG, String.valueOf(message.getSentTimeMillis()), e);
throw new InsecureFallbackApprovalException(e);
} catch (FileNotFoundException e) {
warn(TAG, String.valueOf(message.getSentTimeMillis()), e);
throw new UndeliverableMessageException(e);
} catch (ServerRejectedException e) {
throw new UndeliverableMessageException(e);
}
}
use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project Signal-Android by WhisperSystems.
the class PushSendJob method getQuoteFor.
protected Optional<SignalServiceDataMessage.Quote> getQuoteFor(OutgoingMediaMessage message) throws IOException {
if (message.getOutgoingQuote() == null)
return Optional.absent();
long quoteId = message.getOutgoingQuote().getId();
String quoteBody = message.getOutgoingQuote().getText();
RecipientId quoteAuthor = message.getOutgoingQuote().getAuthor();
List<SignalServiceDataMessage.Mention> quoteMentions = getMentionsFor(message.getOutgoingQuote().getMentions());
List<SignalServiceDataMessage.Quote.QuotedAttachment> quoteAttachments = new LinkedList<>();
List<Attachment> filteredAttachments = Stream.of(message.getOutgoingQuote().getAttachments()).filterNot(a -> MediaUtil.isViewOnceType(a.getContentType())).toList();
for (Attachment attachment : filteredAttachments) {
BitmapUtil.ScaleResult thumbnailData = null;
SignalServiceAttachment thumbnail = null;
String thumbnailType = MediaUtil.IMAGE_JPEG;
try {
if (MediaUtil.isImageType(attachment.getContentType()) && attachment.getUri() != null) {
Bitmap.CompressFormat format = BitmapUtil.getCompressFormatForContentType(attachment.getContentType());
thumbnailData = BitmapUtil.createScaledBytes(context, new DecryptableStreamUriLoader.DecryptableUri(attachment.getUri()), 100, 100, 500 * 1024, format);
thumbnailType = attachment.getContentType();
} else if (Build.VERSION.SDK_INT >= 23 && MediaUtil.isVideoType(attachment.getContentType()) && attachment.getUri() != null) {
Bitmap bitmap = MediaUtil.getVideoThumbnail(context, attachment.getUri(), 1000);
if (bitmap != null) {
thumbnailData = BitmapUtil.createScaledBytes(context, bitmap, 100, 100, 500 * 1024);
}
}
if (thumbnailData != null) {
SignalServiceAttachment.Builder builder = SignalServiceAttachment.newStreamBuilder().withContentType(thumbnailType).withWidth(thumbnailData.getWidth()).withHeight(thumbnailData.getHeight()).withLength(thumbnailData.getBitmap().length).withStream(new ByteArrayInputStream(thumbnailData.getBitmap())).withResumableUploadSpec(ApplicationDependencies.getSignalServiceMessageSender().getResumableUploadSpec());
thumbnail = builder.build();
}
quoteAttachments.add(new SignalServiceDataMessage.Quote.QuotedAttachment(attachment.isVideoGif() ? MediaUtil.IMAGE_GIF : attachment.getContentType(), attachment.getFileName(), thumbnail));
} catch (BitmapDecodingException e) {
Log.w(TAG, e);
}
}
Recipient quoteAuthorRecipient = Recipient.resolved(quoteAuthor);
if (quoteAuthorRecipient.isMaybeRegistered()) {
SignalServiceAddress quoteAddress = RecipientUtil.toSignalServiceAddress(context, quoteAuthorRecipient);
return Optional.of(new SignalServiceDataMessage.Quote(quoteId, quoteAddress, quoteBody, quoteAttachments, quoteMentions));
} else {
return Optional.absent();
}
}
use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project Signal-Android by WhisperSystems.
the class MultiDeviceContactUpdateJob method getVerifiedMessage.
private Optional<VerifiedMessage> getVerifiedMessage(Recipient recipient, Optional<IdentityRecord> identity) throws InvalidNumberException, IOException {
if (!identity.isPresent())
return Optional.absent();
SignalServiceAddress destination = RecipientUtil.toSignalServiceAddress(context, recipient);
IdentityKey identityKey = identity.get().getIdentityKey();
VerifiedMessage.VerifiedState state;
switch(identity.get().getVerifiedStatus()) {
case VERIFIED:
state = VerifiedMessage.VerifiedState.VERIFIED;
break;
case UNVERIFIED:
state = VerifiedMessage.VerifiedState.UNVERIFIED;
break;
case DEFAULT:
state = VerifiedMessage.VerifiedState.DEFAULT;
break;
default:
throw new AssertionError("Unknown state: " + identity.get().getVerifiedStatus());
}
return Optional.of(new VerifiedMessage(destination, identityKey, state, System.currentTimeMillis()));
}
use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project Signal-Android by WhisperSystems.
the class MultiDeviceVerifiedUpdateJob method onRun.
@Override
public void onRun() throws IOException, UntrustedIdentityException {
if (!Recipient.self().isRegistered()) {
throw new NotPushRegisteredException();
}
try {
if (!TextSecurePreferences.isMultiDevice(context)) {
Log.i(TAG, "Not multi device...");
return;
}
if (destination == null) {
Log.w(TAG, "No destination...");
return;
}
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
Recipient recipient = Recipient.resolved(destination);
if (recipient.isUnregistered()) {
Log.w(TAG, recipient.getId() + " not registered!");
return;
}
VerifiedMessage.VerifiedState verifiedState = getVerifiedState(verifiedStatus);
SignalServiceAddress verifiedAddress = RecipientUtil.toSignalServiceAddress(context, recipient);
VerifiedMessage verifiedMessage = new VerifiedMessage(verifiedAddress, new IdentityKey(identityKey, 0), verifiedState, timestamp);
messageSender.sendSyncMessage(SignalServiceSyncMessage.forVerified(verifiedMessage), UnidentifiedAccessUtil.getAccessFor(context, recipient));
} catch (InvalidKeyException e) {
throw new IOException(e);
}
}
use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project Signal-Android by WhisperSystems.
the class MultiDeviceGroupUpdateJob method onRun.
@Override
public void onRun() throws Exception {
if (!Recipient.self().isRegistered()) {
throw new NotPushRegisteredException();
}
if (!TextSecurePreferences.isMultiDevice(context)) {
Log.i(TAG, "Not multi device, aborting...");
return;
}
if (SignalStore.account().isLinkedDevice()) {
Log.i(TAG, "Not primary device, aborting...");
return;
}
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pipe[0]);
Uri uri = BlobProvider.getInstance().forData(inputStream, 0).withFileName("multidevice-group-update").createForSingleSessionOnDiskAsync(context, () -> Log.i(TAG, "Write successful."), e -> Log.w(TAG, "Error during write.", e));
try (GroupDatabase.Reader reader = SignalDatabase.groups().getGroups()) {
DeviceGroupsOutputStream out = new DeviceGroupsOutputStream(new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]));
boolean hasData = false;
GroupDatabase.GroupRecord record;
while ((record = reader.getNext()) != null) {
if (record.isV1Group()) {
List<SignalServiceAddress> members = new LinkedList<>();
List<Recipient> registeredMembers = RecipientUtil.getEligibleForSending(Recipient.resolvedList(record.getMembers()));
for (Recipient member : registeredMembers) {
members.add(RecipientUtil.toSignalServiceAddress(context, member));
}
RecipientId recipientId = SignalDatabase.recipients().getOrInsertFromPossiblyMigratedGroupId(record.getId());
Recipient recipient = Recipient.resolved(recipientId);
Optional<Integer> expirationTimer = recipient.getExpiresInSeconds() > 0 ? Optional.of(recipient.getExpiresInSeconds()) : Optional.absent();
Map<RecipientId, Integer> inboxPositions = SignalDatabase.threads().getInboxPositions();
Set<RecipientId> archived = SignalDatabase.threads().getArchivedRecipients();
out.write(new DeviceGroup(record.getId().getDecodedId(), Optional.fromNullable(record.getTitle()), members, getAvatar(record.getRecipientId()), record.isActive(), expirationTimer, Optional.of(ChatColorsMapper.getMaterialColor(recipient.getChatColors()).serialize()), recipient.isBlocked(), Optional.fromNullable(inboxPositions.get(recipientId)), archived.contains(recipientId)));
hasData = true;
}
}
out.close();
if (hasData) {
long length = BlobProvider.getInstance().calculateFileSize(context, uri);
sendUpdate(ApplicationDependencies.getSignalServiceMessageSender(), BlobProvider.getInstance().getStream(context, uri), length);
} else {
Log.w(TAG, "No groups present for sync message. Sending an empty update.");
sendUpdate(ApplicationDependencies.getSignalServiceMessageSender(), null, 0);
}
} finally {
BlobProvider.getInstance().delete(context, uri);
}
}
Aggregations