package org.thoughtcrime.securesms.util; import static org.thoughtcrime.securesms.util.ShareUtil.getForwardedMessageIDs; import static org.thoughtcrime.securesms.util.ShareUtil.getSharedText; import static org.thoughtcrime.securesms.util.ShareUtil.getSharedUris; import static org.thoughtcrime.securesms.util.ShareUtil.isForwarding; import static org.thoughtcrime.securesms.util.ShareUtil.isSharing; import static org.thoughtcrime.securesms.util.ShareUtil.resetRelayingMessageContent; import android.app.Activity; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.util.Log; import android.provider.OpenableColumns; import com.b44t.messenger.DcContext; import com.b44t.messenger.DcMsg; import org.thoughtcrime.securesms.ConversationListRelayingActivity; import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.providers.PersistentBlobProvider; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.ArrayList; public class SendRelayedMessageUtil { private static final String TAG = SendRelayedMessageUtil.class.getSimpleName(); public static void immediatelyRelay(Activity activity, int chatId) { immediatelyRelay(activity, new Long[]{(long) chatId}); } public static void immediatelyRelay(Activity activity, final Long[] chatIds) { ConversationListRelayingActivity.finishActivity(); if (isForwarding(activity)) { int[] forwardedMessageIDs = getForwardedMessageIDs(activity); resetRelayingMessageContent(activity); if (forwardedMessageIDs == null) return; Util.runOnAnyBackgroundThread(() -> { DcContext dcContext = DcHelper.getContext(activity); for (long longChatId : chatIds) { int chatId = (int) longChatId; if (dcContext.getChat(chatId).isSelfTalk()) { for (int msgId : forwardedMessageIDs) { DcMsg msg = dcContext.getMsg(msgId); if (msg.canSave() && msg.getSavedMsgId() == 0 && msg.getChatId() != chatId) { dcContext.saveMsgs(new int[]{msgId}); } else { handleForwarding(activity, chatId, new int[]{msgId}); } } } else { handleForwarding(activity, chatId, forwardedMessageIDs); } } }); } else if (isSharing(activity)) { ArrayList sharedUris = getSharedUris(activity); String sharedText = getSharedText(activity); String subject = ShareUtil.getSharedSubject(activity); String sharedHtml = getHtml(activity, ShareUtil.getSharedHtml(activity)); String msgType = ShareUtil.getSharedType(activity); resetRelayingMessageContent(activity); Util.runOnAnyBackgroundThread(() -> { for (long chatId : chatIds) { sendMultipleMsgs(activity, (int) chatId, sharedUris, msgType, sharedHtml, subject, sharedText); } }); } } private static void handleForwarding(Context context, int chatId, int[] forwardedMessageIDs) { DcContext dcContext = DcHelper.getContext(context); dcContext.forwardMsgs(forwardedMessageIDs, chatId); } public static void sendMultipleMsgs(Context context, int chatId, ArrayList sharedUris, String sharedText) { sendMultipleMsgs(context, chatId, sharedUris, null, null, null, sharedText); } private static void sendMultipleMsgs(Context context, int chatId, ArrayList sharedUris, String msgType, String sharedHtml, String subject, String sharedText) { DcContext dcContext = DcHelper.getContext(context); ArrayList uris = sharedUris; String text = sharedText; if (uris.size() == 1) { dcContext.sendMsg(chatId, createMessage(context, uris.get(0), msgType, sharedHtml, subject, text)); } else { if (text != null || sharedHtml != null) { dcContext.sendMsg(chatId, createMessage(context, null, null, sharedHtml, subject, text)); } for (Uri uri : uris) { dcContext.sendMsg(chatId, createMessage(context, uri, null, null, subject, null)); } } } public static boolean containsVideoType(Context context, ArrayList uris) { for (final Uri uri : uris) { final String mimeType = MediaUtil.getMimeType(context, uri); if (MediaUtil.isVideoType(mimeType)) { return true; } } return false; } public static DcMsg createMessage(Context context, Uri uri, String type, String html, String subject, String text) throws NullPointerException { DcContext dcContext = DcHelper.getContext(context); DcMsg message; String mimeType = MediaUtil.getMimeType(context, uri); if (uri == null) { message = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT); } else if ("sticker".equals(type)) { message = new DcMsg(dcContext, DcMsg.DC_MSG_STICKER); message.forceSticker(); } else if ("image".equals(type) || MediaUtil.isImageType(mimeType)) { message = new DcMsg(dcContext, DcMsg.DC_MSG_IMAGE); } else if ("audio".equals(type) || MediaUtil.isAudioType(mimeType)) { message = new DcMsg(dcContext, DcMsg.DC_MSG_AUDIO); } else if ("video".equals(type) || MediaUtil.isVideoType(mimeType)) { message = new DcMsg(dcContext, DcMsg.DC_MSG_VIDEO); } else { message = new DcMsg(dcContext, DcMsg.DC_MSG_FILE); } if (uri != null) { setFileFromUri(context, uri, message, mimeType); } if (html != null) { message.setHtml(html); } if (subject != null) { message.setSubject(subject); } if (text != null) { message.setText(text); } return message; } private static void setFileFromUri(Context context, Uri uri, DcMsg message, String mimeType) { String path; DcContext dcContext = DcHelper.getContext(context); String filename = "cannot-resolve.jpg"; // best guess, this still leads to most images being workable if OS does weird things try { if (PartAuthority.isLocalUri(uri)) { filename = uri.getPathSegments().get(PersistentBlobProvider.FILENAME_PATH_SEGMENT); } else if (uri.getScheme().equals("content")) { final ContentResolver contentResolver = context.getContentResolver(); final Cursor cursor = contentResolver.query(uri, null, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { final int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); if (nameIndex >= 0) { filename = cursor.getString(nameIndex); } } } finally { cursor.close(); } } path = DcHelper.getBlobdirFile(dcContext, filename, "temp"); // copy content to this file if (path != null) { InputStream inputStream = PartAuthority.getAttachmentStream(context, uri); OutputStream outputStream = new FileOutputStream(path); Util.copy(inputStream, outputStream); } } catch (Exception e) { e.printStackTrace(); path = null; } message.setFileAndDeduplicate(path, filename, mimeType); } private static String getHtml(Context context, Uri uri) { try { InputStream in = PartAuthority.getAttachmentStream(context, uri); BufferedReader br = new BufferedReader(new InputStreamReader(in)); StringBuilder html = new StringBuilder(); for (String line; (line = br.readLine()) != null; ) { html.append(line).append('\n'); } if (in != null) in.close(); br.close(); return html.toString(); } catch (Exception ex) { Log.e(TAG, "failed to get HTML", ex); return null; } } }