From a84dcf6a8eda78d5b94588731e344751dab13cea Mon Sep 17 00:00:00 2001
From: Jake McGinty <me@jake.su>
Date: Tue, 28 Jul 2015 13:17:01 -0700
Subject: [PATCH] assert gif size constraints before OOMEs

fixes #3778
closes #3833
// FREEBIE
---
 res/values/strings.xml                               |  1 +
 .../thoughtcrime/securesms/ConversationActivity.java |  6 ++++++
 .../securesms/mms/AttachmentManager.java             |  4 +++-
 src/org/thoughtcrime/securesms/mms/AudioSlide.java   |  2 +-
 src/org/thoughtcrime/securesms/mms/GifSlide.java     | 12 +++++++++++-
 .../thoughtcrime/securesms/mms/MediaConstraints.java |  5 ++++-
 src/org/thoughtcrime/securesms/mms/Slide.java        |  4 ++--
 src/org/thoughtcrime/securesms/mms/VideoSlide.java   |  2 +-
 8 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/res/values/strings.xml b/res/values/strings.xml
index acdcb41b70..aa177eece8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -98,6 +98,7 @@
     <string name="ConversationActivity_select_contact_info">Select contact info</string>
     <string name="ConversationActivity_compose_message">Compose message</string>
     <string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Sorry, there was an error setting your attachment.</string>
+    <string name="ConversationActivity_the_gif_you_selected_was_too_big">The gif you selected was too big!</string>
     <string name="ConversationActivity_sorry_the_selected_video_exceeds_message_size_restrictions">Sorry, the selected video exceeds message size restrictions (%1$skB).</string>
     <string name="ConversationActivity_sorry_the_selected_audio_exceeds_message_size_restrictions">Sorry, the selected audio exceeds message size restrictions (%1$skB).</string>
     <string name="ConversationActivity_recipient_is_not_a_valid_sms_or_email_address_exclamation">Recipient is not a valid SMS or email address!</string>
diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java
index cfec8a0c87..ed63b85f42 100644
--- a/src/org/thoughtcrime/securesms/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationActivity.java
@@ -86,6 +86,7 @@ import org.thoughtcrime.securesms.database.MmsSmsColumns.Types;
 import org.thoughtcrime.securesms.database.ThreadDatabase;
 import org.thoughtcrime.securesms.mms.AttachmentManager;
 import org.thoughtcrime.securesms.mms.AttachmentTypeSelectorAdapter;
+import org.thoughtcrime.securesms.mms.MediaConstraints;
 import org.thoughtcrime.securesms.mms.MediaTooLargeException;
 import org.thoughtcrime.securesms.mms.MmsMediaConstraints;
 import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
@@ -931,6 +932,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
       attachmentManager.clear();
       Toast.makeText(this, R.string.ConversationActivity_sorry_there_was_an_error_setting_your_attachment,
                      Toast.LENGTH_LONG).show();
+    } catch (MediaTooLargeException e) {
+      attachmentManager.clear();
+      Toast.makeText(this, getString(R.string.ConversationActivity_the_gif_you_selected_was_too_big),
+                     Toast.LENGTH_LONG).show();
+      Log.w(TAG, e);
     }
   }
 
diff --git a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java
index 71fdda5417..a88ee81cd8 100644
--- a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java
+++ b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java
@@ -87,7 +87,9 @@ public class AttachmentManager {
     captureUri = null;
   }
 
-  public void setImage(MasterSecret masterSecret, Uri image) throws IOException, BitmapDecodingException {
+  public void setImage(MasterSecret masterSecret, Uri image)
+      throws IOException, BitmapDecodingException, MediaTooLargeException
+  {
     if (MediaUtil.isGif(MediaUtil.getMimeType(context, image))) {
       setMedia(new GifSlide(context, masterSecret, image), masterSecret);
     } else {
diff --git a/src/org/thoughtcrime/securesms/mms/AudioSlide.java b/src/org/thoughtcrime/securesms/mms/AudioSlide.java
index 3086c8b3b0..68bc123bc2 100644
--- a/src/org/thoughtcrime/securesms/mms/AudioSlide.java
+++ b/src/org/thoughtcrime/securesms/mms/AudioSlide.java
@@ -59,7 +59,7 @@ public class AudioSlide extends Slide {
   public static PduPart constructPartFromUri(Context context, Uri uri) throws IOException, MediaTooLargeException {
     PduPart part = new PduPart();
 
-    assertMediaSize(context, uri);
+    assertMediaSize(context, uri, MmsMediaConstraints.MAX_MESSAGE_SIZE);
 
     Cursor cursor = null;
 
diff --git a/src/org/thoughtcrime/securesms/mms/GifSlide.java b/src/org/thoughtcrime/securesms/mms/GifSlide.java
index e858373d89..4c87c25742 100644
--- a/src/org/thoughtcrime/securesms/mms/GifSlide.java
+++ b/src/org/thoughtcrime/securesms/mms/GifSlide.java
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.mms;
 
 import android.content.Context;
 import android.net.Uri;
+import android.provider.MediaStore.Audio.Media;
 
 import org.thoughtcrime.securesms.crypto.MasterSecret;
 import org.thoughtcrime.securesms.util.BitmapDecodingException;
@@ -16,9 +17,18 @@ public class GifSlide extends ImageSlide {
   }
 
   public GifSlide(Context context, MasterSecret masterSecret, Uri uri)
-      throws IOException, BitmapDecodingException
+      throws IOException, BitmapDecodingException, MediaTooLargeException
   {
     super(context, masterSecret, uri);
+    assertMediaSize();
+  }
+
+  private void assertMediaSize() throws MediaTooLargeException, IOException {
+    // TODO move assertion outside of slides and take available transport options into account
+    assertMediaSize(context, getPart().getDataUri(), MediaConstraints.PUSH_CONSTRAINTS.getGifMaxSize());
+    if (!MediaConstraints.PUSH_CONSTRAINTS.isSatisfied(context, masterSecret, part)) {
+      throw new MediaTooLargeException("Media exceeds maximum message size.");
+    }
   }
 
   @Override public Uri getThumbnailUri() {
diff --git a/src/org/thoughtcrime/securesms/mms/MediaConstraints.java b/src/org/thoughtcrime/securesms/mms/MediaConstraints.java
index ddf7b89537..90de4d46d1 100644
--- a/src/org/thoughtcrime/securesms/mms/MediaConstraints.java
+++ b/src/org/thoughtcrime/securesms/mms/MediaConstraints.java
@@ -5,6 +5,9 @@ import android.net.Uri;
 import android.util.Log;
 import android.util.Pair;
 
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.gifdecoder.GifDecoder;
+
 import org.thoughtcrime.securesms.crypto.MasterSecret;
 import org.thoughtcrime.securesms.util.BitmapDecodingException;
 import org.thoughtcrime.securesms.util.BitmapUtil;
@@ -33,7 +36,7 @@ public abstract class MediaConstraints {
 
   public boolean isSatisfied(Context context, MasterSecret masterSecret, PduPart part) {
     try {
-      return (MediaUtil.isGif(part)    && part.getDataSize() <= getGifMaxSize()) ||
+      return (MediaUtil.isGif(part)    && part.getDataSize() <= getGifMaxSize()   && isWithinBounds(context, masterSecret, part.getDataUri())) ||
              (MediaUtil.isImage(part)  && part.getDataSize() <= getImageMaxSize() && isWithinBounds(context, masterSecret, part.getDataUri())) ||
              (MediaUtil.isAudio(part)  && part.getDataSize() <= getAudioMaxSize()) ||
              (MediaUtil.isVideo(part)  && part.getDataSize() <= getVideoMaxSize()) ||
diff --git a/src/org/thoughtcrime/securesms/mms/Slide.java b/src/org/thoughtcrime/securesms/mms/Slide.java
index b4ce8bc981..6eb5f14648 100644
--- a/src/org/thoughtcrime/securesms/mms/Slide.java
+++ b/src/org/thoughtcrime/securesms/mms/Slide.java
@@ -86,7 +86,7 @@ public abstract class Slide {
     return !getPart().getPartId().isValid();
   }
 
-  protected static void assertMediaSize(Context context, Uri uri)
+  protected static void assertMediaSize(Context context, Uri uri, long max)
       throws MediaTooLargeException, IOException
   {
     InputStream in = context.getContentResolver().openInputStream(uri);
@@ -96,7 +96,7 @@ public abstract class Slide {
 
     while ((read = in.read(buffer)) != -1) {
       size += read;
-      if (size > MmsMediaConstraints.MAX_MESSAGE_SIZE) throw new MediaTooLargeException("Media exceeds maximum message size.");
+      if (size > max) throw new MediaTooLargeException("Media exceeds maximum message size.");
     }
   }
 
diff --git a/src/org/thoughtcrime/securesms/mms/VideoSlide.java b/src/org/thoughtcrime/securesms/mms/VideoSlide.java
index fb3e3f33a4..d8f4d9b61a 100644
--- a/src/org/thoughtcrime/securesms/mms/VideoSlide.java
+++ b/src/org/thoughtcrime/securesms/mms/VideoSlide.java
@@ -76,7 +76,7 @@ public class VideoSlide extends Slide {
         cursor.close();
     }
 
-    assertMediaSize(context, uri);
+    assertMediaSize(context, uri, MmsMediaConstraints.MAX_MESSAGE_SIZE);
     part.setDataUri(uri);
     part.setContentId((System.currentTimeMillis()+"").getBytes());
     part.setName(("Video" + System.currentTimeMillis()).getBytes());