package ysoserial.payloads;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.Callable;

import org.junit.Assert;

import com.google.common.io.Files;

import ysoserial.CustomTest;
import ysoserial.util.OS;

/**
 * @author mbechler
 *
 */
public class FileUploadTest implements CustomTest {

    /**
     *
     */
    private static final byte[] FDATA = new byte[] {(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
    private File source;
    private File repo;


    /**
     *
     */
    public FileUploadTest () {
        try {
            source = File.createTempFile("fut", "-source");
            repo = Files.createTempDir();
        }
        catch ( IOException e ) {
            e.printStackTrace();
        }
    }


    public synchronized void run ( Callable<Object> payload ) throws Exception {
        try {
            Files.write(FDATA, this.source);
            Assert.assertTrue(this.source.exists());
            payload.call();

            File found = null;
            for ( File f : this.repo.listFiles()) {
                found = f;
                break;
            }
            Assert.assertNotNull("File not copied", found);
            if (OS.get() != OS.WINDOWS) {
                // windows' file locking seems to cause this to fail
                Assert.assertFalse("Source not deleted", this.source.exists());
            }
            Assert.assertTrue("Contents not copied", Arrays.equals(FDATA, Files.toByteArray(found)));
        } finally {
            if ( this.repo.exists()) {
                for ( File f : this.repo.listFiles()) {
                    f.deleteOnExit();
                }
                this.repo.deleteOnExit();
            }
            this.source.deleteOnExit();
        }
    }

    public String getPayloadArgs () {
        return "copyAndDelete;" + this.source.getAbsolutePath() + ";" + this.repo.getAbsolutePath();
    }

}

@@ -1069,33 +1069,125 @@
            for (
- 
+int i = 0; i %3C 50 && found == null; i++) %7B // try for 5s before failing%0A                for (
 File f : this.re
@@ -1196,32 +1196,36 @@
 .listFiles()) %7B%0A
+    
                 
@@ -1255,15 +1255,72 @@
     
+    
 break;%0A
+                %7D%0A                Thread.sleep(100);%0A
     
@@ -1835,11 +1835,13 @@
     
-f.d
+safeD
 elet
@@ -1840,32 +1840,33 @@
 afeDeleteOnExit(
+f
 );%0A             
@@ -1890,19 +1890,13 @@
     
-this.repo.d
+safeD
 elet
@@ -1895,32 +1895,41 @@
 afeDeleteOnExit(
+this.repo
 );%0A            %7D
@@ -1945,32 +1945,260 @@
     
-this.source.deleteOnExit
+safeDeleteOnExit(this.source);%0A        %7D%0A    %7D%0A%0A    private static void safeDeleteOnExit(File f) %7B%0A        try %7B%0A            if (f.exists()) %7B%0A                f.deleteOnExit();%0A            %7D%0A        %7D catch (Exception e) %7B%0A            e.printStackTrace
 ();%0A

fix (hopefully) test flakiness