package de.thedevstack.conversationsplus.utils; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import java.net.MalformedURLException; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; import de.thedevstack.conversationsplus.ConversationsPlusApplication; import de.thedevstack.conversationsplus.entities.Conversation; import de.thedevstack.conversationsplus.entities.DownloadableFile; import de.thedevstack.conversationsplus.entities.FileParams; import de.thedevstack.conversationsplus.entities.Message; import de.thedevstack.conversationsplus.entities.Transferable; import de.thedevstack.conversationsplus.enums.FileStatus; import de.thedevstack.conversationsplus.persistance.DatabaseBackend; import de.thedevstack.conversationsplus.persistance.FileBackend; /** * Utility class to work with messages. */ public final class MessageUtil { public static void extractFileParamsFromBody(Message message) { if (null == message) { return; } // Ensure that for every message the fileParams are set after calling this method FileParams fileParams = message.getFileParams(); if (null == fileParams) { fileParams = new FileParams(); message.setFileParams(fileParams); } String body = message.getBody(); /** * there are a few cases where spaces result in an unwanted behavior, e.g. * "http://example.com/image.jpg" text that will not be shown /abc.png" * or more than one image link in one message. */ if (null == body || body.isEmpty() || body.contains(" ")) { return; } try { URL url = new URL(body); if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { message.setTreatAsDownloadable(Message.Decision.NEVER); return; } String extension = FileUtils.getRelevantExtension(url); if (message.isHttpUploaded()) { fileParams.setUrl(url.toString()); if (null != extension && (Transferable.WELL_KNOWN_EXTENSIONS.contains(extension.toLowerCase()) || Transferable.VALID_IMAGE_EXTENSIONS.contains(extension.toLowerCase()))) { message.setTreatAsDownloadable(Message.Decision.MUST); } else { message.setTreatAsDownloadable(Message.Decision.NEVER); fileParams.setFileStatus(FileStatus.UNDEFINED); } extractFilename(message, url.toString()); return; } if (extension == null) { message.setTreatAsDownloadable(Message.Decision.NEVER); return; } byte[] ivAndKey = UrlUtil.getIvAndKeyFromURL(url); if (null != ivAndKey) { if (MimeUtils.guessMimeTypeFromExtension(extension) != null) { message.setTreatAsDownloadable(Message.Decision.MUST); fileParams.setKeyAndIv(ivAndKey); } else { message.setTreatAsDownloadable(Message.Decision.NEVER); } } else if (Transferable.VALID_IMAGE_EXTENSIONS.contains(extension) || Transferable.WELL_KNOWN_EXTENSIONS.contains(extension)) { message.setTreatAsDownloadable(Message.Decision.SHOULD); } else { message.setTreatAsDownloadable(Message.Decision.NEVER); } if (message.treatAsDownloadable() == Message.Decision.MUST || message.treatAsDownloadable() == Message.Decision.SHOULD) { fileParams.setUrl(url.toString()); extractFilename(message, url.toString()); } } catch (MalformedURLException e) { message.setTreatAsDownloadable(Message.Decision.NEVER); } } private static void extractFilename(Message message, String url) { String originalFilename = FileUtils.getFilenameFromPath(url); final String lowerCaseFilename = originalFilename.toLowerCase(); final String lastPart = FileUtils.getLastExtension(lowerCaseFilename); detectAndSetEncryption(lastPart, message); String filenameExtension; if (!lastPart.isEmpty() && Transferable.VALID_CRYPTO_EXTENSIONS.contains(lastPart)) { filenameExtension = FileUtils.getSecondToLastExtension(lowerCaseFilename); originalFilename = originalFilename.replace("." + lastPart, ""); } else { filenameExtension = lastPart; } message.setRelativeFilePath(message.getUuid() + "." + filenameExtension); message.getFileParams().setOriginalFilename(originalFilename); } private static void detectAndSetEncryption(String lastPart, Message message) { if (!lastPart.isEmpty() && ("pgp".equals(lastPart) || "gpg".equals(lastPart))) { message.setEncryption(Message.ENCRYPTION_PGP); } else if (message.getEncryption() != Message.ENCRYPTION_OTR && message.getEncryption() != Message.ENCRYPTION_AXOLOTL) { message.setEncryption(Message.ENCRYPTION_NONE); } else if ((message.getEncryption() == Message.ENCRYPTION_OTR || message.getEncryption() == Message.ENCRYPTION_AXOLOTL) && message.getFileParams() != null && message.getFileParams().getKey() == null) { // If an encryption is set for the message, but no key given -> decryption not possible message.setEncryption(Message.ENCRYPTION_NONE); } } /** * Checks if an attached file is an image or not. * Prerequisite for calling this method: The check if a file is attached is done before. * @param message * @return */ public static boolean isAttachedFileAnImage(Message message) { final FileParams fileParams = message.getFileParams(); String mimeType = (null != fileParams) ? fileParams.getMimeType() : null; return message.getType() == Message.TYPE_IMAGE || (fileParams != null && fileParams.getWidth() > 0) || (null != mimeType && mimeType.startsWith("image/")); } public static boolean isTypeFileAndDecrypted(Message message) { return message.getType() == Message.TYPE_FILE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED; } public static boolean isDecrypted(Message message) { return message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED; } /** * Checks if the file status of an message is NOT one of: *