use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by WhisperSystems.
the class AttachmentDownloadJob method retrieveAttachment.
private void retrieveAttachment(long messageId, final AttachmentId attachmentId, final Attachment attachment) throws IOException, RetryLaterException {
AttachmentDatabase database = SignalDatabase.attachments();
File attachmentFile = database.getOrCreateTransferFile(attachmentId);
try {
SignalServiceMessageReceiver messageReceiver = ApplicationDependencies.getSignalServiceMessageReceiver();
SignalServiceAttachmentPointer pointer = createAttachmentPointer(attachment);
InputStream stream = messageReceiver.retrieveAttachment(pointer, attachmentFile, MAX_ATTACHMENT_SIZE, (total, progress) -> EventBus.getDefault().postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.NETWORK, total, progress)));
database.insertAttachmentsForPlaceholder(messageId, attachmentId, stream);
} catch (RangeException e) {
Log.w(TAG, "Range exception, file size " + attachmentFile.length(), e);
if (attachmentFile.delete()) {
Log.i(TAG, "Deleted temp download file to recover");
throw new RetryLaterException(e);
} else {
throw new IOException("Failed to delete temp download file following range exception");
}
} catch (InvalidPartException | NonSuccessfulResponseCodeException | InvalidMessageException | MmsException | MissingConfigurationException e) {
Log.w(TAG, "Experienced exception while trying to download an attachment.", e);
markFailed(messageId, attachmentId);
}
}
use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by WhisperSystems.
the class AttachmentCompressionJob method compress.
private void compress(@NonNull AttachmentDatabase attachmentDatabase, @NonNull MediaConstraints constraints, @NonNull DatabaseAttachment attachment) throws UndeliverableMessageException {
try {
if (attachment.isSticker()) {
Log.d(TAG, "Sticker, not compressing.");
} else if (MediaUtil.isVideo(attachment)) {
Log.i(TAG, "Compressing video.");
attachment = transcodeVideoIfNeededToDatabase(context, attachmentDatabase, attachment, constraints, EventBus.getDefault(), this::isCanceled);
if (!constraints.isSatisfied(context, attachment)) {
throw new UndeliverableMessageException("Size constraints could not be met on video!");
}
} else if (constraints.canResize(attachment)) {
Log.i(TAG, "Compressing image.");
MediaStream converted = compressImage(context, attachment, constraints);
attachmentDatabase.updateAttachmentData(attachment, converted, false);
attachmentDatabase.markAttachmentAsTransformed(attachmentId);
} else if (constraints.isSatisfied(context, attachment)) {
Log.i(TAG, "Not compressing.");
attachmentDatabase.markAttachmentAsTransformed(attachmentId);
} else {
throw new UndeliverableMessageException("Size constraints could not be met!");
}
} catch (IOException | MmsException e) {
throw new UndeliverableMessageException(e);
}
}
use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by WhisperSystems.
the class MmsDatabase method getOutgoingMessage.
@Override
public OutgoingMediaMessage getOutgoingMessage(long messageId) throws MmsException, NoSuchMessageException {
AttachmentDatabase attachmentDatabase = SignalDatabase.attachments();
MentionDatabase mentionDatabase = SignalDatabase.mentions();
Cursor cursor = null;
try {
cursor = rawQuery(RAW_ID_WHERE, new String[] { String.valueOf(messageId) });
if (cursor != null && cursor.moveToNext()) {
List<DatabaseAttachment> associatedAttachments = attachmentDatabase.getAttachmentsForMessage(messageId);
List<Mention> mentions = mentionDatabase.getMentionsForMessage(messageId);
long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
String body = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID));
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
boolean viewOnce = cursor.getLong(cursor.getColumnIndexOrThrow(VIEW_ONCE)) == 1;
long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(RECIPIENT_ID));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
int distributionType = SignalDatabase.threads().getDistributionType(threadId);
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
long quoteId = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_ID));
long quoteAuthor = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_AUTHOR));
String quoteText = cursor.getString(cursor.getColumnIndexOrThrow(QUOTE_BODY));
boolean quoteMissing = cursor.getInt(cursor.getColumnIndexOrThrow(QUOTE_MISSING)) == 1;
List<Attachment> quoteAttachments = Stream.of(associatedAttachments).filter(Attachment::isQuote).map(a -> (Attachment) a).toList();
List<Mention> quoteMentions = parseQuoteMentions(context, cursor);
List<Contact> contacts = getSharedContacts(cursor, associatedAttachments);
Set<Attachment> contactAttachments = new HashSet<>(Stream.of(contacts).map(Contact::getAvatarAttachment).filter(a -> a != null).toList());
List<LinkPreview> previews = getLinkPreviews(cursor, associatedAttachments);
Set<Attachment> previewAttachments = Stream.of(previews).filter(lp -> lp.getThumbnail().isPresent()).map(lp -> lp.getThumbnail().get()).collect(Collectors.toSet());
List<Attachment> attachments = Stream.of(associatedAttachments).filterNot(Attachment::isQuote).filterNot(contactAttachments::contains).filterNot(previewAttachments::contains).sorted(new DatabaseAttachment.DisplayOrderComparator()).map(a -> (Attachment) a).toList();
Recipient recipient = Recipient.resolved(RecipientId.from(recipientId));
Set<NetworkFailure> networkFailures = new HashSet<>();
Set<IdentityKeyMismatch> mismatches = new HashSet<>();
QuoteModel quote = null;
if (quoteId > 0 && quoteAuthor > 0 && (!TextUtils.isEmpty(quoteText) || !quoteAttachments.isEmpty())) {
quote = new QuoteModel(quoteId, RecipientId.from(quoteAuthor), quoteText, quoteMissing, quoteAttachments, quoteMentions);
}
if (!TextUtils.isEmpty(mismatchDocument)) {
try {
mismatches = JsonUtils.fromJson(mismatchDocument, IdentityKeyMismatchSet.class).getItems();
} catch (IOException e) {
Log.w(TAG, e);
}
}
if (!TextUtils.isEmpty(networkDocument)) {
try {
networkFailures = JsonUtils.fromJson(networkDocument, NetworkFailureSet.class).getItems();
} catch (IOException e) {
Log.w(TAG, e);
}
}
if (body != null && (Types.isGroupQuit(outboxType) || Types.isGroupUpdate(outboxType))) {
return new OutgoingGroupUpdateMessage(recipient, new MessageGroupContext(body, Types.isGroupV2(outboxType)), attachments, timestamp, 0, false, quote, contacts, previews, mentions);
} else if (Types.isExpirationTimerUpdate(outboxType)) {
return new OutgoingExpirationUpdateMessage(recipient, timestamp, expiresIn);
}
OutgoingMediaMessage message = new OutgoingMediaMessage(recipient, body, attachments, timestamp, subscriptionId, expiresIn, viewOnce, distributionType, quote, contacts, previews, mentions, networkFailures, mismatches);
if (Types.isSecureType(outboxType)) {
return new OutgoingSecureMediaMessage(message);
}
return message;
}
throw new NoSuchMessageException("No record found for id: " + messageId);
} catch (IOException e) {
throw new MmsException(e);
} finally {
if (cursor != null)
cursor.close();
}
}
use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by WhisperSystems.
the class AttachmentDatabase method setAttachmentData.
@NonNull
private DataInfo setAttachmentData(@NonNull File destination, @NonNull InputStream in, @Nullable AttachmentId attachmentId) throws MmsException {
try {
File tempFile = newFile();
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
DigestInputStream digestInputStream = new DigestInputStream(in, messageDigest);
Pair<byte[], OutputStream> out = ModernEncryptingPartOutputStream.createFor(attachmentSecret, tempFile, false);
long length = StreamUtil.copy(digestInputStream, out.second);
String hash = Base64.encodeBytes(digestInputStream.getMessageDigest().digest());
if (!tempFile.renameTo(destination)) {
Log.w(TAG, "Couldn't rename " + tempFile.getPath() + " to " + destination.getPath());
tempFile.delete();
throw new IllegalStateException("Couldn't rename " + tempFile.getPath() + " to " + destination.getPath());
}
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
Optional<DataInfo> sharedDataInfo = findDuplicateDataFileInfo(database, hash, attachmentId);
if (sharedDataInfo.isPresent()) {
Log.i(TAG, "[setAttachmentData] Duplicate data file found! " + sharedDataInfo.get().file.getAbsolutePath());
if (!destination.equals(sharedDataInfo.get().file) && destination.delete()) {
Log.i(TAG, "[setAttachmentData] Deleted original file. " + destination);
}
return sharedDataInfo.get();
} else {
Log.i(TAG, "[setAttachmentData] No matching attachment data found. " + destination.getAbsolutePath());
}
return new DataInfo(destination, length, out.first, hash);
} catch (IOException | NoSuchAlgorithmException e) {
throw new MmsException(e);
}
}
use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by WhisperSystems.
the class AttachmentDatabase method copyAttachmentData.
public void copyAttachmentData(@NonNull AttachmentId sourceId, @NonNull AttachmentId destinationId) throws MmsException {
DatabaseAttachment sourceAttachment = getAttachment(sourceId);
if (sourceAttachment == null) {
throw new MmsException("Cannot find attachment for source!");
}
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
DataInfo sourceDataInfo = getAttachmentDataFileInfo(sourceId, DATA);
if (sourceDataInfo == null) {
throw new MmsException("No attachment data found for source!");
}
ContentValues contentValues = new ContentValues();
contentValues.put(DATA, sourceDataInfo.file.getAbsolutePath());
contentValues.put(DATA_HASH, sourceDataInfo.hash);
contentValues.put(SIZE, sourceDataInfo.length);
contentValues.put(DATA_RANDOM, sourceDataInfo.random);
contentValues.put(TRANSFER_STATE, sourceAttachment.getTransferState());
contentValues.put(CDN_NUMBER, sourceAttachment.getCdnNumber());
contentValues.put(CONTENT_LOCATION, sourceAttachment.getLocation());
contentValues.put(DIGEST, sourceAttachment.getDigest());
contentValues.put(CONTENT_DISPOSITION, sourceAttachment.getKey());
contentValues.put(NAME, sourceAttachment.getRelay());
contentValues.put(SIZE, sourceAttachment.getSize());
contentValues.put(FAST_PREFLIGHT_ID, sourceAttachment.getFastPreflightId());
contentValues.put(WIDTH, sourceAttachment.getWidth());
contentValues.put(HEIGHT, sourceAttachment.getHeight());
contentValues.put(CONTENT_TYPE, sourceAttachment.getContentType());
contentValues.put(VISUAL_HASH, getVisualHashStringOrNull(sourceAttachment));
database.update(TABLE_NAME, contentValues, PART_ID_WHERE, destinationId.toStrings());
}
Aggregations