package fuzion24.device.vulnerability.vulnerabilities.framework.media;

import android.content.Context;
import android.content.res.AssetManager;
import android.os.Build;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import fuzion24.device.vulnerability.vulnerabilities.VulnerabilityTest;

/**
 * Created by fuzion24 on 8/10/15.
 */

public class StageFright {

    private static final String TAG = "StageFright";

    private static void exec(String blah) throws Exception {
        Runtime.getRuntime().exec(blah);
    }

    public static List<VulnerabilityTest> getTests(Context context) {
        try {
            File dataDir = context.getFilesDir();

            AssetManager assetManager = context.getAssets();
            final String stageFrightAssetPath = "stagefright/stagefright_media_files";
            String[] stagefrightMediaFiles = assetManager.list(stageFrightAssetPath);

            List<VulnerabilityTest> tests = new ArrayList<VulnerabilityTest>();

            final String extractedBinaryTester = dataDir.getAbsolutePath() + File.separator + getNativeAppName();
            extractAsset(context, "stagefright" + File.separator + getNativeAppName(),
                    extractedBinaryTester);

            exec("chmod 744 " + extractedBinaryTester);

            for (final String mediaFile : stagefrightMediaFiles) {

                final String extractedAssetPath = dataDir.getAbsolutePath() + File.separator + mediaFile;

                extractAsset(context,
                        stageFrightAssetPath + File.separator + mediaFile,
                        extractedAssetPath);

                tests.add(new VulnerabilityTest() {
                    @Override
                    public String getName() {
                        return "StageFright: " + mediaFile;
                    }

                    @Override
                    public boolean isVulnerable(Context context) throws Exception {
                        testMedia(extractedBinaryTester, extractedAssetPath);
                        return false;
                    }
                });
            }

            return tests;
        }catch(Exception e){
            e.printStackTrace();
        }

        return new ArrayList<VulnerabilityTest>();
    }

    private static int testMedia(String binary, String media) throws Exception {
        Process process = Runtime.getRuntime().exec(binary + " " + media);
        InputStream is = process.getInputStream();
        return process.waitFor();
    }


    private static final int BUFFER_SIZE = 2 * 1024 * 1024;
    private static void copy(InputStream input, OutputStream output) throws IOException {
        try {
            byte[] buffer = new byte[BUFFER_SIZE];
            int bytesRead = input.read(buffer);
            while (bytesRead != -1) {
                output.write(buffer, 0, bytesRead);
                bytesRead = input.read(buffer);
            }
            //If needed, close streams.
        } finally {
            input.close();
            output.close();
        }
    }


    private static void extractAsset(Context ctx, String name, String destination) throws Exception {
        Log.d(TAG, "Extracting \'" + name + "\' from assets to \'" + destination + "\' ...");

        try {
            File f = new File(destination);
            if(f.exists()) {
                f.delete();
            }
        }
        catch(Exception e) {e.printStackTrace();}

        AssetManager assetManager = ctx.getAssets();
        InputStream asset = assetManager.open(name);
        FileOutputStream fos = new FileOutputStream(destination);
        copy(asset,fos);

    }

    public static String getNativeAppName() {
        return Build.VERSION.SDK_INT >= 16 ? "stagefrightCheck-pie" : "stagefrightCheck";
    }

}

@@ -189,16 +189,200 @@
 l.Log;%0A%0A
+import org.apache.commons.compress.utils.Charsets;%0Aimport org.apache.commons.compress.utils.IOUtils;%0Aimport org.apache.commons.io.FilenameUtils;%0A%0Aimport java.io.ByteArrayOutputStream;%0A
 import j
@@ -475,32 +475,66 @@
 io.InputStream;%0A
+import java.io.InputStreamReader;%0A
 import java.io.O
@@ -596,16 +596,42 @@
 il.List;
+%0Aimport java.util.Scanner;
 %0A%0Aimport
@@ -2193,24 +2193,54 @@
 Fright: %22 + 
+FilenameUtils.removeExtension(
 mediaFile;%0A 
@@ -2236,16 +2236,17 @@
 ediaFile
+)
 ;%0A      
@@ -2396,24 +2396,31 @@
             
+return 
 testMedia(ex
@@ -2465,46 +2465,8 @@
 h);%0A
-                        return false;%0A
     
@@ -2694,19 +2694,23 @@
  static 
-int
+boolean
  testMed
@@ -2886,24 +2886,25 @@
 ream();%0A
+%0A
         
 return p
@@ -2895,22 +2895,309 @@
         
-return
+String content = readFully(is, Charsets.UTF_8.displayName());%0A        String errStream = readFully(process.getErrorStream(), Charsets.UTF_8.displayName());%0A%0A        if(errStream.contains(%22Fatal signal%22) %7C%7C content.contains(%22Boom goes the dynamite%22))%7B%0A            return true;%0A        %7D%0A       
  process
@@ -3208,26 +3208,47 @@
 tFor();%0A    
+    return false;%0A    
 %7D
-%0A
 %0A%0A    privat
@@ -3784,16 +3784,574 @@
 %0A    %7D%0A%0A
+    public static String readFully(InputStream inputStream, String encoding)%0A            throws IOException %7B%0A        return new String(readFully(inputStream), encoding);%0A    %7D%0A%0A%0A    private static byte%5B%5D readFully(InputStream inputStream)%0A            throws IOException %7B%0A        ByteArrayOutputStream baos = new ByteArrayOutputStream();%0A        byte%5B%5D buffer = new byte%5B1024%5D;%0A        int length = 0;%0A        while ((length = inputStream.read(buffer)) != -1) %7B%0A            baos.write(buffer, 0, length);%0A        %7D%0A        return baos.toByteArray();%0A    %7D%0A%0A
 %0A    pri

Check output of binary to see if it crashed or or we caught a bad signal