package org.thoughtcrime.securesms.util; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId; import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment; import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import java.util.Collections; import java.util.Set; public class AttachmentUtil { private static final String TAG = AttachmentUtil.class.getSimpleName(); @WorkerThread public static boolean isAutoDownloadPermitted(@NonNull Context context, @Nullable DatabaseAttachment attachment) { if (attachment == null) { Log.w(TAG, "attachment was null, returning vacuous true"); return true; } if (isFromUnknownContact(context, attachment)) { return false; } Set allowedTypes = getAllowedAutoDownloadTypes(context); String contentType = attachment.getContentType(); if (attachment.isVoiceNote() || (MediaUtil.isAudio(attachment) && TextUtils.isEmpty(attachment.getFileName())) || MediaUtil.isLongTextType(attachment.getContentType())) { return true; } else if (isNonDocumentType(contentType)) { return allowedTypes.contains(MediaUtil.getDiscreteMimeType(contentType)); } else { return allowedTypes.contains("documents"); } } /** * Deletes the specified attachment. If its the only attachment for its linked message, the entire * message is deleted. */ @WorkerThread public static void deleteAttachment(@NonNull Context context, @NonNull DatabaseAttachment attachment) { AttachmentId attachmentId = attachment.getAttachmentId(); long mmsId = attachment.getMmsId(); int attachmentCount = DatabaseComponent.get(context).attachmentDatabase() .getAttachmentsForMessage(mmsId) .size(); if (attachmentCount <= 1) { DatabaseComponent.get(context).mmsDatabase().deleteMessage(mmsId); } else { DatabaseComponent.get(context).attachmentDatabase().deleteAttachment(attachmentId); } } private static boolean isNonDocumentType(String contentType) { return MediaUtil.isImageType(contentType) || MediaUtil.isVideoType(contentType) || MediaUtil.isAudioType(contentType); } private static @NonNull Set getAllowedAutoDownloadTypes(@NonNull Context context) { if (isConnectedWifi(context)) return TextSecurePreferences.getWifiMediaDownloadAllowed(context); else if (isConnectedRoaming(context)) return TextSecurePreferences.getRoamingMediaDownloadAllowed(context); else if (isConnectedMobile(context)) return TextSecurePreferences.getMobileMediaDownloadAllowed(context); else return Collections.emptySet(); } private static NetworkInfo getNetworkInfo(@NonNull Context context) { return ServiceUtil.getConnectivityManager(context).getActiveNetworkInfo(); } private static boolean isConnectedWifi(@NonNull Context context) { final NetworkInfo info = getNetworkInfo(context); return info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI; } private static boolean isConnectedMobile(@NonNull Context context) { final NetworkInfo info = getNetworkInfo(context); return info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_MOBILE; } private static boolean isConnectedRoaming(@NonNull Context context) { final NetworkInfo info = getNetworkInfo(context); return info != null && info.isConnected() && info.isRoaming() && info.getType() == ConnectivityManager.TYPE_MOBILE; } @WorkerThread private static boolean isFromUnknownContact(@NonNull Context context, @NonNull DatabaseAttachment attachment) { // We don't allow attachments to be sent unless we're friends with someone or the attachment is sent // in a group context. Auto-downloading attachments is therefore fine. return false; } }