aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/eu/siacs/conversations/persistance/FileBackend.java')
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/FileBackend.java233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
new file mode 100644
index 00000000..a90e14e6
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
@@ -0,0 +1,233 @@
+package eu.siacs.conversations.persistance;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Locale;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Environment;
+import android.util.Log;
+import android.webkit.MimeTypeMap;
+
+import de.thedevstack.conversationsplus.ConversationsPlusApplication;
+import de.thedevstack.conversationsplus.exceptions.FileCopyException;
+import de.thedevstack.conversationsplus.utils.ImageUtil;
+import de.thedevstack.conversationsplus.utils.StreamUtil;
+
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Transferable;
+import eu.siacs.conversations.entities.DownloadableFile;
+import eu.siacs.conversations.entities.Message;
+
+public final class FileBackend {
+
+ private static int IMAGE_SIZE = 1920;
+
+ private static final SimpleDateFormat imageDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
+
+ public static DownloadableFile getFile(Message message) {
+ return getFile(message, true);
+ }
+
+ public static DownloadableFile getFile(Message message, boolean decrypted) {
+ String path = message.getRelativeFilePath();
+ String extension;
+ if (path != null && !path.isEmpty()) {
+ String[] parts = path.split("\\.");
+ extension = "."+parts[parts.length - 1];
+ } else {
+ if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_TEXT) {
+ extension = ".webp";
+ } else {
+ extension = "";
+ }
+ path = message.getUuid()+extension;
+ }
+ final boolean encrypted = !decrypted
+ && (message.getEncryption() == Message.ENCRYPTION_PGP
+ || message.getEncryption() == Message.ENCRYPTION_DECRYPTED);
+ if (encrypted) {
+ return new DownloadableFile(getConversationsFileDirectory()+message.getUuid()+extension+".pgp");
+ } else {
+ if (path.startsWith("/")) {
+ return new DownloadableFile(path);
+ } else {
+ if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension)) {
+ return new DownloadableFile(getConversationsFileDirectory() + path);
+ } else {
+ return new DownloadableFile(getConversationsImageDirectory() + path);
+ }
+ }
+ }
+ }
+
+ public static String getConversationsFileDirectory() {
+ return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Conversations/";
+ }
+
+ public static String getConversationsImageDirectory() {
+ return Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_PICTURES).getAbsolutePath()
+ + "/Conversations/";
+ }
+
+ public static DownloadableFile copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException {
+ Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage");
+ String mime = ConversationsPlusApplication.getInstance().getContentResolver().getType(uri);
+ String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime);
+ message.setRelativeFilePath(message.getUuid() + "." + extension);
+ DownloadableFile file = getFile(message);
+ file.getParentFile().mkdirs();
+ OutputStream os = null;
+ InputStream is = null;
+ try {
+ file.createNewFile();
+ os = new FileOutputStream(file);
+ is = StreamUtil.openInputStreamFromContentResolver(uri);
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = is.read(buffer)) > 0) {
+ os.write(buffer, 0, length);
+ }
+ os.flush();
+ } catch(FileNotFoundException e) {
+ throw new FileCopyException(R.string.error_file_not_found);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new FileCopyException(R.string.error_io_exception);
+ } finally {
+ StreamUtil.close(os);
+ StreamUtil.close(is);
+ }
+ Log.d(Config.LOGTAG, "output file name " + file);
+ return file;
+ }
+
+ public static DownloadableFile copyImageToPrivateStorage(Message message, Uri image)
+ throws FileCopyException {
+ return copyImageToPrivateStorage(message, image, 0);
+ }
+
+ private static DownloadableFile copyImageToPrivateStorage(Message message,
+ Uri image, int sampleSize) throws FileCopyException {
+ DownloadableFile file = getFile(message);
+ file.getParentFile().mkdirs();
+ InputStream is = null;
+ OutputStream os = null;
+ try {
+ file.createNewFile();
+ is = StreamUtil.openInputStreamFromContentResolver(image);
+ os = new FileOutputStream(file);
+
+ Bitmap originalBitmap;
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ int inSampleSize = (int) Math.pow(2, sampleSize);
+ Log.d(Config.LOGTAG, "reading bitmap with sample size " + inSampleSize);
+ options.inSampleSize = inSampleSize;
+ originalBitmap = BitmapFactory.decodeStream(is, null, options);
+ is.close();
+ if (originalBitmap == null) {
+ throw new FileCopyException(R.string.error_not_an_image_file);
+ }
+ Bitmap scaledBitmap = ImageUtil.resize(originalBitmap, IMAGE_SIZE);
+ int rotation = ImageUtil.getRotation(image);
+ if (rotation > 0) {
+ scaledBitmap = ImageUtil.rotate(scaledBitmap, rotation);
+ }
+
+ boolean success = scaledBitmap.compress(Bitmap.CompressFormat.WEBP, 75, os);
+ if (!success) {
+ throw new FileCopyException(R.string.error_compressing_image);
+ }
+ os.flush();
+ long size = file.getSize();
+ int width = scaledBitmap.getWidth();
+ int height = scaledBitmap.getHeight();
+ message.setBody(Long.toString(size) + '|' + width + '|' + height);
+ return file;
+ } catch (FileNotFoundException e) {
+ throw new FileCopyException(R.string.error_file_not_found);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new FileCopyException(R.string.error_io_exception);
+ } catch (SecurityException e) {
+ throw new FileCopyException(R.string.error_security_exception_during_image_copy);
+ } catch (OutOfMemoryError e) {
+ ++sampleSize;
+ if (sampleSize <= 3) {
+ return copyImageToPrivateStorage(message, image, sampleSize);
+ } else {
+ throw new FileCopyException(R.string.error_out_of_memory);
+ }
+ } catch (NullPointerException e) {
+ throw new FileCopyException(R.string.error_io_exception);
+ } finally {
+ StreamUtil.close(os);
+ StreamUtil.close(is);
+ }
+ }
+
+ public static Uri getTakePhotoUri() {
+ StringBuilder pathBuilder = new StringBuilder();
+ pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
+ pathBuilder.append('/');
+ pathBuilder.append("Camera");
+ pathBuilder.append('/');
+ pathBuilder.append("IMG_" + imageDateFormat.format(new Date()) + ".jpg");
+ Uri uri = Uri.parse("file://" + pathBuilder.toString());
+ File file = new File(uri.toString());
+ file.getParentFile().mkdirs();
+ return uri;
+ }
+
+ public static Uri getJingleFileUri(Message message) {
+ File file = getFile(message);
+ return Uri.parse("file://" + file.getAbsolutePath());
+ }
+
+ public static void updateFileParams(Message message) {
+ updateFileParams(message,null);
+ }
+
+ public static void updateFileParams(Message message, URL url) {
+ DownloadableFile file = getFile(message);
+ if (message.getType() == Message.TYPE_IMAGE || file.getMimeType().startsWith("image/")) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(file.getAbsolutePath(), options);
+ int imageHeight = options.outHeight;
+ int imageWidth = options.outWidth;
+ if (url == null) {
+ message.setBody(Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight);
+ } else {
+ message.setBody(url.toString()+"|"+Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight);
+ }
+ } else {
+ if (url != null) {
+ message.setBody(url.toString()+"|"+Long.toString(file.getSize()));
+ } else {
+ message.setBody(Long.toString(file.getSize()));
+ }
+ }
+
+ }
+
+ public static boolean isFileAvailable(Message message) {
+ return getFile(message).exists();
+ }
+
+ private FileBackend() {
+ // Static helper class
+ }
+}