/*
 * Copyright (C) 2013 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package android.util.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.util.jar.StrictJarFile;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.zip.ZipEntry;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class StrictJarFileTest {
    // A well formed jar file with 6 entries.
    private static final String JAR_1 = "hyts_patch.jar";

    private File mResourcesFile;

    @Before
    public void setup() {
        try {
            mResourcesFile = File.createTempFile("sjf_resources", "", null);
            mResourcesFile.delete();
            mResourcesFile.mkdirs();
        } catch (IOException e) {
            throw new RuntimeException("Unable to create temp folder", e);
        }
        mResourcesFile.deleteOnExit();
    }

    @Test(expected=IOException.class)
    public void testConstructorWrongFile() throws IOException {
        new StrictJarFile("Wrong.file");
    }

    @Test(expected=IOException.class)
    public void testConstructorWrongFile_FD() throws IOException {
        new StrictJarFile(new FileDescriptor());
    }

    @Test(expected=NullPointerException.class)
    public void testConstructorWrongFile_FD_null() throws IOException {
        new StrictJarFile((FileDescriptor) null);
    }

    @Test
    public void testConstructor() throws Exception {
        copyFile(JAR_1);
        String fileName = (new File(mResourcesFile, JAR_1)).getCanonicalPath();
        StrictJarFile jarFile = new StrictJarFile(fileName);
        jarFile.close();
    }

    @Test
    public void testConstructor_FD() throws Exception {
        copyFile(JAR_1);
        FileDescriptor fd = createReadOnlyFileDescriptor(
                new File(mResourcesFile, JAR_1).getAbsolutePath());
        StrictJarFile jarFile = new StrictJarFile(fd);
        jarFile.close();
    }

    @Test
    public void testIteration() throws Exception {
        copyFile(JAR_1);
        StrictJarFile jarFile =
                new StrictJarFile(new File(mResourcesFile, JAR_1).getAbsolutePath());
        checkIteration(jarFile);
    }

    @Test
    public void testIteration_FD() throws Exception {
        copyFile(JAR_1);
        FileDescriptor fd = createReadOnlyFileDescriptor(
                new File(mResourcesFile, JAR_1).getAbsolutePath());
        StrictJarFile jarFile = new StrictJarFile(fd);
        checkIteration(jarFile);
    }

    private static void checkIteration(StrictJarFile jarFile) throws Exception {
        Iterator<ZipEntry> it = jarFile.iterator();
        HashMap<String, ZipEntry> entries = new HashMap<>();
        while (it.hasNext()) {
            final ZipEntry ze = it.next();
            entries.put(ze.getName(), ze);
        }

        assertEquals(6, entries.size());
        assertTrue(entries.containsKey("META-INF/"));

        assertTrue(entries.containsKey("META-INF/MANIFEST.MF"));
        ZipEntry ze = entries.get("META-INF/MANIFEST.MF");
        assertEquals(62, ze.getSize());
        assertEquals(ZipEntry.DEFLATED, ze.getMethod());
        assertEquals(61, ze.getCompressedSize());

        assertTrue(entries.containsKey("Blah.txt"));
        ze = entries.get("Blah.txt");
        assertEquals(4, ze.getSize());
        assertEquals(ZipEntry.DEFLATED, ze.getMethod());
        assertEquals(6, ze.getCompressedSize());
        assertEquals("Blah", readUtf8String(jarFile.getInputStream(ze)));

        assertTrue(entries.containsKey("foo/"));
        assertTrue(entries.containsKey("foo/bar/"));
        assertTrue(entries.containsKey("foo/bar/A.class"));
        ze = entries.get("foo/bar/A.class");
        assertEquals(311, ze.getSize());
        assertEquals(ZipEntry.DEFLATED, ze.getMethod());
        assertEquals(225, ze.getCompressedSize());
    }

    @Test
    public void testFindEntry() throws Exception {
        copyFile(JAR_1);
        StrictJarFile jarFile =
                new StrictJarFile(new File(mResourcesFile, JAR_1).getAbsolutePath());
        checkFindEntry(jarFile);
    }

    @Test
    public void testFindEntry_FD() throws Exception {
        copyFile(JAR_1);
        FileDescriptor fd = createReadOnlyFileDescriptor(
                new File(mResourcesFile, JAR_1).getAbsolutePath());
        StrictJarFile jarFile = new StrictJarFile(fd);
        checkFindEntry(jarFile);
    }

    private static void checkFindEntry(StrictJarFile jarFile) throws Exception {
        assertNull(jarFile.findEntry("foobar"));
        assertNull(jarFile.findEntry("blah.txt"));
        assertNotNull(jarFile.findEntry("Blah.txt"));
        final ZipEntry ze = jarFile.findEntry("Blah.txt");
        assertEquals(4, ze.getSize());
        assertEquals(ZipEntry.DEFLATED, ze.getMethod());
        assertEquals(6, ze.getCompressedSize());
        assertEquals("Blah", readUtf8String(jarFile.getInputStream(ze)));
    }

    @Test
    public void testGetManifest() throws Exception {
        copyFile(JAR_1);
        StrictJarFile jarFile =
                new StrictJarFile(new File(mResourcesFile, JAR_1).getAbsolutePath());
        checkGetManifest(jarFile);
    }

    @Test
    public void testGetManifest_FD() throws Exception {
        copyFile(JAR_1);
        FileDescriptor fd = createReadOnlyFileDescriptor(
                new File(mResourcesFile, JAR_1).getAbsolutePath());
        StrictJarFile jarFile = new StrictJarFile(fd);
        checkGetManifest(jarFile);
    }

    private static void checkGetManifest(StrictJarFile jarFile) throws Exception {
        assertNotNull(jarFile.getManifest());
        assertEquals("1.4.2 (IBM Corporation)",
                jarFile.getManifest().getMainAttributes().getValue("Created-By"));
    }

    @Test
    public void testJarSigning_wellFormed() throws IOException {
        copyFile("Integrate.jar");
        StrictJarFile jarFile =
                new StrictJarFile(new File(mResourcesFile, "Integrate.jar").getAbsolutePath());
        checkJarSigning_wellFormed(jarFile);
    }

    @Test
    public void testJarSigning_wellFormed_FD() throws IOException {
        copyFile("Integrate.jar");
        FileDescriptor fd = createReadOnlyFileDescriptor(
                new File(mResourcesFile, "Integrate.jar").getAbsolutePath());
        StrictJarFile jarFile = new StrictJarFile(fd);
        checkJarSigning_wellFormed(jarFile);
    }

    private static void checkJarSigning_wellFormed(StrictJarFile jarFile) throws IOException {
        Iterator<ZipEntry> entries = jarFile.iterator();
        while (entries.hasNext()) {
            ZipEntry zipEntry = entries.next();
            jarFile.getInputStream(zipEntry).skip(Long.MAX_VALUE);
            if ("Test.class".equals(zipEntry.getName())) {
                assertNotNull(jarFile.getCertificates(zipEntry));
                assertNotNull(jarFile.getCertificateChains(zipEntry));
            }
        }
    }

    @Test
    public void testJarSigning_fudgedEntry() throws IOException {
        copyFile("Integrate.jar");
        StrictJarFile jarFile = new StrictJarFile(
                new File(mResourcesFile, "Integrate.jar").getAbsolutePath());
        checkJarSigning_fudgedEntry(jarFile);
    }

    @Test
    public void testJarSigning_fudgedEntry_FD() throws IOException {
        copyFile("Integrate.jar");
        FileDescriptor fd = createReadOnlyFileDescriptor(
                new File(mResourcesFile, "Integrate.jar").getAbsolutePath());
        StrictJarFile jarFile = new StrictJarFile(fd);
        checkJarSigning_fudgedEntry(jarFile);
    }

    private static void checkJarSigning_fudgedEntry(StrictJarFile jarFile) throws IOException {
        ZipEntry ze = jarFile.findEntry("Test.class");
        jarFile.getInputStream(ze).skip(Long.MAX_VALUE);

        // Fudge the size so that certificates do not match.
        ze.setSize(ze.getSize() - 1);
        try {
            jarFile.getInputStream(ze).skip(Long.MAX_VALUE);
            fail();
        } catch (SecurityException expected) {
        }
    }

    @Test
    public void testJarSigning_modifiedClass() throws IOException {
        copyFile("Modified_Class.jar");
        StrictJarFile jarFile = new StrictJarFile(
                new File(mResourcesFile,  "Modified_Class.jar").getAbsolutePath());
        checkJarSigning_modifiedClass(jarFile);
    }

    @Test
    public void testJarSigning_modifiedClass_FD() throws IOException {
        copyFile("Modified_Class.jar");
        FileDescriptor fd = createReadOnlyFileDescriptor(
                new File(mResourcesFile, "Modified_Class.jar").getAbsolutePath());
        StrictJarFile jarFile = new StrictJarFile(fd);
        checkJarSigning_modifiedClass(jarFile);
    }

    private static void checkJarSigning_modifiedClass(StrictJarFile jarFile)
            throws IOException {
        ZipEntry ze = jarFile.findEntry("Test.class");
        try {
            jarFile.getInputStream(ze).skip(Long.MAX_VALUE);
            fail();
        } catch (SecurityException expected) {
        }
    }

    @Test
    public void testJarSigning_brokenMainAttributes() throws Exception {
        verifyThrowsOnInit("Modified_Manifest_MainAttributes.jar");
    }

    @Test
    public void testJarSigning_brokenMainAttributes_FD() throws Exception {
        verifyThrowsOnInitFD("Modified_Manifest_MainAttributes.jar");
    }

    @Test
    public void testJarSigning_brokenEntryAttributes() throws Exception {
        verifyThrowsOnInit("Modified_Manifest_EntryAttributes.jar");
    }

    @Test
    public void testJarSigning_brokenEntryAttributes_FD() throws Exception {
        verifyThrowsOnInitFD("Modified_Manifest_EntryAttributes.jar");
    }

    @Test
    public void testJarSigning_brokenSignatureFile() throws Exception {
        verifyThrowsOnInit("Modified_SF_EntryAttributes.jar");
    }

    @Test
    public void testJarSigning_brokenSignatureFile_FD() throws Exception {
        verifyThrowsOnInitFD("Modified_SF_EntryAttributes.jar");
    }

    @Test
    public void testJarSigning_removedEntry() throws Exception {
        verifyThrowsOnInit("removed.jar");
    }

    @Test
    public void testJarSigning_removedEntry_FD() throws Exception {
        verifyThrowsOnInitFD("removed.jar");
    }

    private void verifyThrowsOnInit(String name) throws Exception {
        copyFile(name);
        try {
            new StrictJarFile(new File(mResourcesFile,  name).getAbsolutePath());
            fail();
        } catch (SecurityException expected) {
        }
    }

    private void verifyThrowsOnInitFD(String name) throws Exception {
        copyFile(name);
        FileDescriptor fd = createReadOnlyFileDescriptor(
                new File(mResourcesFile, name).getAbsolutePath());
        try {
            new StrictJarFile(fd);
            fail();
        } catch (SecurityException expected) {
        }
    }

    private static FileDescriptor createReadOnlyFileDescriptor(String path) throws IOException {
        final int mode = 0;
        try {
            return Os.open(path, OsConstants.O_RDONLY, mode);
        } catch (ErrnoException e) {
            throw new IOException(e);
        }
    }

    private static String readUtf8String(InputStream inputStream) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(128);
        byte[] readBuffer = new byte[128];
        int byteCount;
        while ((byteCount = inputStream.read(readBuffer)) != -1) {
            baos.write(readBuffer, 0, byteCount);
        }
        return new String(baos.toByteArray(), StandardCharsets.UTF_8);
    }

    private File copyFile(String file) {
        File dest = new File(mResourcesFile.toString() + "/" + file);

        if (!dest.exists()) {
            try {
                InputStream in = InstrumentationRegistry.getTargetContext().getAssets().open(file);
                FileOutputStream out = new FileOutputStream(dest);
                byte[] buffer = new byte[8192];
                int c;
                while ((c = in.read(buffer)) != -1) {
                    out.write(buffer, 0, c);
                }
                out.close();
                dest.deleteOnExit();
                in.close();
            } catch (IOException e) {
                throw new RuntimeException("Unable to copy file from resource " + file
                        + " to file " + dest, e);
            }
        }
        return dest;
    }
}
