changeset 1286:b8cd8b45a3d4

Add SOPBypass reproducer Added new tests to check where applets are allow to make network connections, depending on different combinations of applet codebase, documentbase, and applet archive location. * tests/reproducers/simple/SOPBypass/resources/SOPBypass.html * tests/reproducers/simple/SOPBypass/resources/SOPBypass.jnlp * tests/reproducers/simple/SOPBypass/srcs/SOPBypass.java * tests/reproducers/simple/SOPBypass/testcases/SOPBypassHtmlAppletTest.java * tests/reproducers/simple/SOPBypass/testcases/SOPBypassJnlpAppletTest.java * tests/reproducers/simple/SOPBypass/testcases/SOPBypassJnlpAppletTestWithHtmlSwitch.java * tests/reproducers/simple/SOPBypass/testcases/SOPBypassUtil.java
author Andrew Azores <aazores@redhat.com>
date Mon, 31 Aug 2015 16:55:32 -0400
parents b1aa74ef87a4
children 531034ce3e30
files ChangeLog tests/reproducers/simple/SOPBypass/resources/SOPBypass.html tests/reproducers/simple/SOPBypass/resources/SOPBypass.jnlp tests/reproducers/simple/SOPBypass/srcs/SOPBypass.java tests/reproducers/simple/SOPBypass/testcases/SOPBypassHtmlAppletTest.java tests/reproducers/simple/SOPBypass/testcases/SOPBypassJnlpAppletTest.java tests/reproducers/simple/SOPBypass/testcases/SOPBypassJnlpAppletTestWithHtmlSwitch.java tests/reproducers/simple/SOPBypass/testcases/SOPBypassUtil.java
diffstat 8 files changed, 1401 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Aug 26 10:18:29 2015 +0200
+++ b/ChangeLog	Mon Aug 31 16:55:32 2015 -0400
@@ -1,3 +1,16 @@
+2015-08-31  Andrew Azores  <aazores@redhat.com>
+
+	Added new tests to check where applets are allow to make network
+	connections, depending on different combinations of applet codebase,
+	documentbase, and applet archive location.
+	* tests/reproducers/simple/SOPBypass/resources/SOPBypass.html
+	* tests/reproducers/simple/SOPBypass/resources/SOPBypass.jnlp
+	* tests/reproducers/simple/SOPBypass/srcs/SOPBypass.java
+	* tests/reproducers/simple/SOPBypass/testcases/SOPBypassHtmlAppletTest.java
+	* tests/reproducers/simple/SOPBypass/testcases/SOPBypassJnlpAppletTest.java
+	* tests/reproducers/simple/SOPBypass/testcases/SOPBypassJnlpAppletTestWithHtmlSwitch.java
+	* tests/reproducers/simple/SOPBypass/testcases/SOPBypassUtil.java
+
 2015-08-25  Jiri Vanek  <jvanek@redhat.com>
             Lukasz Dracz  <ldracz@redhat.com>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/SOPBypass/resources/SOPBypass.html	Mon Aug 31 16:55:32 2015 -0400
@@ -0,0 +1,49 @@
+<!--
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+
+ -->
+<html>
+  <head></head>
+  <body>
+  <applet  
+            CODE_REPLACEMENT_TOKEN
+            ARCHIVE_REPLACEMENT_TOKEN
+            CODEBASE_REPLACEMENT_TOKEN
+            width="800"
+            height="600">
+    </applet>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/SOPBypass/resources/SOPBypass.jnlp	Mon Aug 31 16:55:32 2015 -0400
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+
+ -->
+<jnlp spec="1.0" href="SOPBypass-filtered.jnlp" codebase="CODEBASE_REPLACEMENT_TOKEN">
+  <information>
+    <title>SOPBypass</title>
+    <vendor>IcedTea</vendor>
+    <homepage href="http://icedtea.classpath.org/wiki/IcedTea-Web#Testing_IcedTea-Web"/>
+    <description>Test applets' abilities to make URLConnections and create Sockets in various documentBase/codebase/etc. combinations</description>
+    <offline/>
+  </information>
+  <resources>
+    <j2se version="1.4+"/>
+    <jar href="JAR_HREF_REPLACEMENT_TOKEN" main="true"/>
+  </resources>
+  <applet-desc
+      documentBase="DOCUMENTBASE_REPLACEMENT_TOKEN"
+      name="SOPBypass"
+      main-class="SOPBypass"
+      width="320"
+      height="200"
+      >
+  </applet-desc>
+</jnlp>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/SOPBypass/srcs/SOPBypass.java	Mon Aug 31 16:55:32 2015 -0400
@@ -0,0 +1,138 @@
+/* SimpleTest1.java
+Copyright (C) 2015 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+import java.applet.Applet;
+import java.io.PrintWriter;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.URL;
+import java.net.URLConnection;
+
+public class SOPBypass extends Applet {
+
+    @Override
+    public void start() {
+        System.out.println("Applet Started");
+
+        System.out.println("Codebase URL: " + getCodeBase());
+        System.out.println("DocumentBase URL: " + getDocumentBase());
+
+        attemptSocketConnectionToCodebase();
+        attemptSocketConnectionToDocumentBase();
+        attemptSocketConnectionToUnrelated();
+        attemptUrlConnectionToCodebase();
+        attemptUrlConnectionToDocumentBase();
+        attemptUrlConnectionToUnrelated();
+
+        System.out.println("*** APPLET FINISHED ***");
+    }
+
+    void attemptSocketConnectionToCodebase() {
+        String host = getCodeBase().getHost();
+        int port = getCodeBase().getPort();;
+        attemptSocketConnection(host, port, "codeBase", true);
+    }
+
+    void attemptSocketConnectionToDocumentBase() {
+        String host = getDocumentBase().getHost();
+        int port = getDocumentBase().getPort();
+        attemptSocketConnection(host, port, "documentBase", true);
+    }
+
+    void attemptSocketConnectionToUnrelated() {
+        String host = "http://example.com";
+        int port = 80;
+        attemptSocketConnection(host, port, "unrelated", false);
+    }
+
+    void attemptSocketConnection(String host, int port, String s, boolean sendData) {
+        boolean connected = true;
+        try {
+            Socket local = new Socket();
+            local.bind(null);
+            local.connect(new InetSocketAddress(host, port));
+            if (sendData) {
+                try (PrintWriter writer = new PrintWriter(local.getOutputStream(), true)) {
+                    writer.println("test");
+                }
+            }
+        } catch (Exception e) {
+            connected = false;
+            e.printStackTrace();
+        }
+        System.out.println("SocketConnection:" + s + " " + connected);
+    }
+
+    void attemptUrlConnectionToCodebase() {
+        attemptUrlConnection(getCodeBase(), "codeBase");
+    }
+
+    void attemptUrlConnectionToDocumentBase() {
+        attemptUrlConnection(getDocumentBase(), "documentBase");
+    }
+
+    void attemptUrlConnectionToUnrelated() {
+        try {
+            attemptUrlConnection(new URL("http://example.com:80"), "unrelated");
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+            System.out.println("Unrelated URL test failed due to MalformedURLException");
+            System.out.println("URLConnection:unrelated false");
+        }
+    }
+
+    void attemptUrlConnection(URL url, String s) {
+        boolean connected = true;
+        try {
+            URLConnection conn = url.openConnection();
+            conn.connect();
+            conn.getContentEncoding();
+            conn.getContentLength();
+            conn.getContentType();
+        } catch (Exception e) {
+            connected = false;
+            e.printStackTrace();
+        }
+        System.out.println("URLConnection:" + s + " " + connected);
+    }
+
+    public static void main(String[] args) {
+        new SOPBypass().start();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/SOPBypass/testcases/SOPBypassHtmlAppletTest.java	Mon Aug 31 16:55:32 2015 -0400
@@ -0,0 +1,255 @@
+/* SOPBypassHtmlAppletTest.java
+   Copyright (C) 2015 Red Hat, Inc.
+
+   This file is part of IcedTea.
+
+   IcedTea is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, version 2.
+
+   IcedTea is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with IcedTea; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package sopbypasstests;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import net.sourceforge.jnlp.annotations.NeedsDisplay;
+import net.sourceforge.jnlp.annotations.TestInBrowsers;
+import net.sourceforge.jnlp.browsertesting.BrowserTest;
+import net.sourceforge.jnlp.browsertesting.Browsers;
+import net.sourceforge.jnlp.ProcessResult;
+import net.sourceforge.jnlp.ServerAccess;
+import net.sourceforge.jnlp.ServerLauncher;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.ManifestAttributesChecker;
+import net.sourceforge.jnlp.tools.DeploymentPropertiesModifier;
+import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel;
+import java.io.File;
+
+import static sopbypasstests.SOPBypassUtil.*;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class SOPBypassHtmlAppletTest extends BrowserTest {
+
+    private static ServerLauncher serverA;
+    private static ServerLauncher serverB;
+    private static ServerLauncher serverC;
+    private static DeploymentPropertiesModifier mod1 = new DeploymentPropertiesModifier();
+    private static DeploymentPropertiesModifier mod2 = new DeploymentPropertiesModifier();
+
+    @BeforeClass
+    public static void setup() throws Exception {
+        serverA = ServerAccess.getIndependentInstance();
+        serverB = ServerAccess.getIndependentInstance();
+        serverC = ServerAccess.getIndependentInstance();
+
+        File file = mod1.src.getFile();
+        if (!file.exists()) {
+            file.getParentFile().mkdirs();
+            file.createNewFile();
+        }
+        mod1.setProperties(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, ManifestAttributesChecker.MANIFEST_ATTRIBUTES_CHECK.NONE.name());
+        mod2.setProperties(DeploymentConfiguration.KEY_SECURITY_LEVEL, AppletSecurityLevel.ALLOW_UNSIGNED.name());
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testLocalAbsoluteArchiveLocalPathCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", server.getUrl("SOPBypass.jar"), server.getUrl("codebase"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testLocalAbsoluteArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", server.getUrl("SOPBypass.jar"), serverC.getUrl("codebase"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testRemoteAbsoluteArchiveSameRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverC.getUrl("SOPBypass.jar"), serverC.getUrl("codebase"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testRemoteAbsoluteArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverB.getUrl("SOPBypass.jar"), serverC.getUrl("codebase"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testRemoteAbsoluteArchiveLocalPathCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverB.getUrl("SOPBypass.jar"), server.getUrl("codebase"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testRemoteAbsoluteArchiveLocalDotCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverB.getUrl("SOPBypass.jar"), ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testRemoteAbsoluteArchiveNoCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverB.getUrl("SOPBypass.jar"), (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testLocalAbsoluteArchiveNoCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", server.getUrl("SOPBypass.jar"), (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testLocalRelativeArchiveNoCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testLocalRelativeArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", serverC.getUrl());
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testLocalAbsoluteArchiveLocalDotCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", server.getUrl("SOPBypass.jar"), ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testLocalRelativeArchiveLocalPathCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", server.getUrl("/"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testLocalRelativeArchiveLocalDotCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    @TestInBrowsers(testIn = {Browsers.one})
+    public void testRemoteRelativeArchiveSameRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", serverC.getUrl("/"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    public ProcessResult performTest(TemplatedHtmlDoc templatedDoc) throws Exception {
+        ProcessResult pr = server.executeBrowser(templatedDoc.getFileName(), getClosingListener(), null);
+        assertStart(pr);
+        assertEnd(pr);
+        return pr;
+    }
+
+    @AfterClass
+    public static void teardown() throws Exception {
+        serverA.stop();
+        serverB.stop();
+        serverC.stop();
+
+        mod1.restoreProperties();
+        mod2.restoreProperties();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/SOPBypass/testcases/SOPBypassJnlpAppletTest.java	Mon Aug 31 16:55:32 2015 -0400
@@ -0,0 +1,238 @@
+/* SOPBypassJnlpAppletTest.java
+   Copyright (C) 2015 Red Hat, Inc.
+
+   This file is part of IcedTea.
+
+   IcedTea is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, version 2.
+
+   IcedTea is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with IcedTea; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package sopbypasstests;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import net.sourceforge.jnlp.annotations.NeedsDisplay;
+import net.sourceforge.jnlp.ProcessResult;
+import net.sourceforge.jnlp.ServerAccess;
+import net.sourceforge.jnlp.ServerLauncher;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.ManifestAttributesChecker;
+import net.sourceforge.jnlp.tools.DeploymentPropertiesModifier;
+import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel;
+import java.io.File;
+
+import static sopbypasstests.SOPBypassUtil.*;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class SOPBypassJnlpAppletTest {
+
+    private static ServerLauncher serverA;
+    private static ServerLauncher serverB;
+    private static ServerLauncher serverC;
+    private static DeploymentPropertiesModifier mod1 = new DeploymentPropertiesModifier();
+    private static DeploymentPropertiesModifier mod2 = new DeploymentPropertiesModifier();
+
+    @BeforeClass
+    public static void setup() throws Exception {
+        serverA = ServerAccess.getIndependentInstance();
+        serverB = ServerAccess.getIndependentInstance();
+        serverC = ServerAccess.getIndependentInstance();
+
+        File file = mod1.src.getFile();
+        if (!file.exists()) {
+            file.getParentFile().mkdirs();
+            file.createNewFile();
+        }
+        mod1.setProperties(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, ManifestAttributesChecker.MANIFEST_ATTRIBUTES_CHECK.NONE.name());
+        mod2.setProperties(DeploymentConfiguration.KEY_SECURITY_LEVEL, AppletSecurityLevel.ALLOW_UNSIGNED.name());
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalAbsoluteArchiveLocalPathCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(server.getUrl("SOPBypass.jar"), server.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalAbsoluteArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(server.getUrl("SOPBypass.jar"), serverC.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveSameRemoteCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(serverC.getUrl("SOPBypass.jar"), serverC.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(serverB.getUrl("SOPBypass.jar"), serverC.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveLocalPathCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(serverB.getUrl("SOPBypass.jar"), server.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveLocalDotCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(serverB.getUrl("SOPBypass.jar"), ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveNoCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(serverB.getUrl("SOPBypass.jar"), (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalAbsoluteArchiveNoCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(server.getUrl("SOPBypass.jar"), (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalRelativeArchiveNoCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp("SOPBypass.jar", (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalRelativeArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp("SOPBypass.jar", serverC.getUrl());
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalAbsoluteArchiveLocalDotCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp(server.getUrl("SOPBypass.jar"), ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalRelativeArchiveLocalPathCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp("SOPBypass.jar", server.getUrl("/"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalRelativeArchiveLocalDotCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp("SOPBypass.jar", ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteRelativeArchiveSameRemoteCodebase() throws Exception {
+        TemplatedJnlpDoc templatedDoc = filterJnlp("SOPBypass.jar", serverC.getUrl("/"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    public ProcessResult performTest(TemplatedJnlpDoc templatedDoc) throws Exception {
+        ProcessResult pr = server.executeJavawsHeadless(templatedDoc.getFileName(), getClosingListener(), null);
+        assertStart(pr);
+        assertEnd(pr);
+        return pr;
+    }
+
+    @AfterClass
+    public static void teardown() throws Exception {
+        serverA.stop();
+        serverB.stop();
+        serverC.stop();
+
+        mod1.restoreProperties();
+        mod2.restoreProperties();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/SOPBypass/testcases/SOPBypassJnlpAppletTestWithHtmlSwitch.java	Mon Aug 31 16:55:32 2015 -0400
@@ -0,0 +1,236 @@
+/* SOPBypassJnlpAppletTestWithHtmlSwitch.java
+   Copyright (C) 2015 Red Hat, Inc.
+
+   This file is part of IcedTea.
+
+   IcedTea is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, version 2.
+
+   IcedTea is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with IcedTea; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package sopbypasstests;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import net.sourceforge.jnlp.annotations.NeedsDisplay;
+import net.sourceforge.jnlp.ProcessResult;
+import net.sourceforge.jnlp.ServerAccess;
+import net.sourceforge.jnlp.ServerLauncher;
+import java.util.Collections;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.ManifestAttributesChecker;
+import net.sourceforge.jnlp.tools.DeploymentPropertiesModifier;
+import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel;
+import java.io.File;
+
+import static sopbypasstests.SOPBypassUtil.*;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class SOPBypassJnlpAppletTestWithHtmlSwitch {
+
+    private static ServerLauncher serverA;
+    private static ServerLauncher serverB;
+    private static ServerLauncher serverC;
+    private static DeploymentPropertiesModifier mod1 = new DeploymentPropertiesModifier();
+    private static DeploymentPropertiesModifier mod2 = new DeploymentPropertiesModifier();
+
+    @BeforeClass
+    public static void setup() throws Exception {
+        serverA = ServerAccess.getIndependentInstance();
+        serverB = ServerAccess.getIndependentInstance();
+        serverC = ServerAccess.getIndependentInstance();
+
+        File file = mod1.src.getFile();
+        if (!file.exists()) {
+            file.getParentFile().mkdirs();
+            file.createNewFile();
+        }
+        mod1.setProperties(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, ManifestAttributesChecker.MANIFEST_ATTRIBUTES_CHECK.NONE.name());
+        mod2.setProperties(DeploymentConfiguration.KEY_SECURITY_LEVEL, AppletSecurityLevel.ALLOW_UNSIGNED.name());
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalAbsoluteArchiveLocalPathCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", server.getUrl("SOPBypass.jar"), server.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalAbsoluteArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", server.getUrl("SOPBypass.jar"), serverC.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveSameRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverC.getUrl("SOPBypass.jar"), serverC.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverB.getUrl("SOPBypass.jar"), serverC.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveLocalPathCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverB.getUrl("SOPBypass.jar"), server.getUrl("."));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveLocalDotCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverB.getUrl("SOPBypass.jar"), ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteAbsoluteArchiveNoCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", serverB.getUrl("SOPBypass.jar"), (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalAbsoluteArchiveNoCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", server.getUrl("SOPBypass.jar"), (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalRelativeArchiveNoCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", (String) null);
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalRelativeArchiveUnrelatedRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", serverC.getUrl());
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalAbsoluteArchiveLocalDotCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", server.getUrl("SOPBypass.jar"), ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalRelativeArchiveLocalPathCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", server.getUrl("/"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testLocalRelativeArchiveLocalDotCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", ".");
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    @Test
+    @NeedsDisplay
+    public void testRemoteRelativeArchiveSameRemoteCodebase() throws Exception {
+        TemplatedHtmlDoc templatedDoc = filterHtml("SOPBypass", "SOPBypass.jar", serverC.getUrl("/"));
+        ProcessResult pr = performTest(templatedDoc);
+        assertCodebaseConnection(pr);
+        assertDocumentBaseConnection(pr);
+        assertNoUnrelatedConnection(pr);
+    }
+
+    public ProcessResult performTest(TemplatedHtmlDoc templatedDoc) throws Exception {
+        ProcessResult pr = server.executeJavawsHeadless(Collections.singletonList("-html"), templatedDoc.getFileName(), getClosingListener(), null, null);
+        assertStart(pr);
+        assertEnd(pr);
+        return pr;
+    }
+
+    @AfterClass
+    public static void teardown() throws Exception {
+        serverA.stop();
+        serverB.stop();
+        serverC.stop();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/SOPBypass/testcases/SOPBypassUtil.java	Mon Aug 31 16:55:32 2015 -0400
@@ -0,0 +1,413 @@
+/* SOPBypassUtil.java
+   Copyright (C) 2015 Red Hat, Inc.
+
+   This file is part of IcedTea.
+
+   IcedTea is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, version 2.
+
+   IcedTea is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with IcedTea; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package sopbypasstests;
+
+import org.junit.AfterClass;
+import org.junit.Test;
+import net.sourceforge.jnlp.browsertesting.BrowserTest;
+import net.sourceforge.jnlp.closinglisteners.AutoOkClosingListener;
+import net.sourceforge.jnlp.closinglisteners.RulesFolowingClosingListener;
+import net.sourceforge.jnlp.ClosingListener;
+import net.sourceforge.jnlp.ProcessResult;
+import net.sourceforge.jnlp.ServerAccess;
+import net.sourceforge.jnlp.ServerAccess.AutoClose;
+import net.sourceforge.jnlp.ServerLauncher;
+import java.net.URL;
+import java.io.File;
+import java.io.IOException;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+public class SOPBypassUtil extends BrowserTest {
+
+    public static final String APPLET_START_STRING = "Applet Started";
+    public static final String APPLET_CLOSE_STRING = AutoOkClosingListener.MAGICAL_OK_CLOSING_STRING;
+
+    public static final String URL_CONNECTION_PREFIX = "URLConnection";
+    public static final String SOCKET_CONNECTION_PREFIX = "SocketConnection";
+    public static final String CONNECTION_DELIMITER = ":";
+    public static final String CODEBASE = "codeBase";
+    public static final String DOCUMENTBASE = "documentBase";
+    public static final String UNRELATED = "unrelated";
+    public static final String SUCCESS = " true";
+    public static final String FAILURE = " false";
+    public static final String URL_CODEBASE = URL_CONNECTION_PREFIX + CONNECTION_DELIMITER + CODEBASE;
+    public static final String URL_CODEBASE_SUCCESS = URL_CODEBASE + SUCCESS;
+    public static final String URL_CODEBASE_FAILURE = URL_CODEBASE + FAILURE;
+    public static final String URL_DOCUMENTBASE = URL_CONNECTION_PREFIX + CONNECTION_DELIMITER + DOCUMENTBASE;
+    public static final String URL_DOCUMENTBASE_SUCCESS = URL_DOCUMENTBASE + SUCCESS;
+    public static final String URL_DOCUMENTBASE_FAILURE = URL_DOCUMENTBASE + FAILURE;
+    public static final String SOCKET_CODEBASE = SOCKET_CONNECTION_PREFIX + CONNECTION_DELIMITER + CODEBASE;
+    public static final String SOCKET_CODEBASE_SUCCESS = SOCKET_CODEBASE + SUCCESS;
+    public static final String SOCKET_CODEBASE_FAILURE = SOCKET_CODEBASE + FAILURE;
+    public static final String SOCKET_DOCUMENTBASE = SOCKET_CONNECTION_PREFIX + CONNECTION_DELIMITER + DOCUMENTBASE;
+    public static final String SOCKET_DOCUMENTBASE_SUCCESS = SOCKET_DOCUMENTBASE + SUCCESS;
+    public static final String SOCKET_DOCUMENTBASE_FAILURE = SOCKET_DOCUMENTBASE + FAILURE;
+    public static final String URL_UNRELATED = URL_CONNECTION_PREFIX + CONNECTION_DELIMITER + UNRELATED;
+    public static final String URL_UNRELATED_SUCCESS = URL_UNRELATED + SUCCESS;
+    public static final String URL_UNRELATED_FAILURE = URL_UNRELATED + FAILURE;
+    public static final String SOCKET_UNRELATED = SOCKET_CONNECTION_PREFIX + CONNECTION_DELIMITER + UNRELATED;
+    public static final String SOCKET_UNRELATED_SUCCESS = SOCKET_UNRELATED + SUCCESS;
+    public static final String SOCKET_UNRELATED_FAILURE = SOCKET_UNRELATED + FAILURE;
+
+    public static TemplatedHtmlDoc filterHtml(String code, String archive, String codebase) throws IOException {
+        TemplatedHtmlDoc templatedDoc = new TemplatedHtmlDoc(server, "SOPBypass.html");
+        templatedDoc.setCode(code);
+        templatedDoc.setArchive(archive);
+        templatedDoc.setCodeBase(codebase);
+        assertFalse(templatedDoc.toString(), templatedDoc.toString().contains("TOKEN"));
+        templatedDoc.save();
+        String content = server.getResourceAsString(templatedDoc.getFileName());
+        assertFalse(content, content.contains("TOKEN"));
+        return templatedDoc;
+    }
+
+    public static TemplatedHtmlDoc filterHtml(String code, URL archive, URL codebase) throws IOException {
+        return filterHtml(code, archive == null ? "" : archive.toString(), codebase == null ? "" : codebase.toString());
+    }
+
+    public static TemplatedHtmlDoc filterHtml(String code, URL archive, String codebase) throws IOException {
+        return filterHtml(code, archive == null ? "" : archive.toString(), codebase);
+    }
+
+    public static TemplatedHtmlDoc filterHtml(String code, String archive, URL codebase) throws IOException {
+        return filterHtml(code, archive, codebase == null ? "" : codebase.toString());
+    }
+
+    public static TemplatedJnlpDoc filterJnlp(String jarHref, String codebase) throws IOException {
+        TemplatedJnlpDoc templatedDoc = new TemplatedJnlpDoc(server, "SOPBypass.jnlp");
+        templatedDoc.setJarHref(jarHref);
+        templatedDoc.setCodeBase(codebase);
+        templatedDoc.setDocumentBase(server.getUrl("SOPBypass.jnlp").toString());
+        assertFalse(templatedDoc.toString(), templatedDoc.toString().contains("TOKEN"));
+        templatedDoc.save();
+        String content = server.getResourceAsString(templatedDoc.getFileName());
+        assertFalse(content, content.contains("TOKEN"));
+        return templatedDoc;
+    }
+
+    public static TemplatedJnlpDoc filterJnlp(URL archive, URL codebase) throws IOException {
+        return filterJnlp(archive == null ? "" : archive.toString(), codebase == null ? "" : codebase.toString());
+    }
+
+    public static TemplatedJnlpDoc filterJnlp(URL archive, String codebase) throws IOException {
+        return filterJnlp(archive == null ? "" : archive.toString(), codebase);
+    }
+
+    public static TemplatedJnlpDoc filterJnlp(String archive, URL codebase) throws IOException {
+        return filterJnlp(archive, codebase == null ? "" : codebase.toString());
+    }
+
+    public static ClosingListener getClosingListener() {
+        RulesFolowingClosingListener listener = new RulesFolowingClosingListener();
+        listener.addContainsRule(APPLET_START_STRING);
+        listener.addContainsRule(APPLET_CLOSE_STRING);
+        return listener;
+    }
+
+    public static void assertStart(ProcessResult pr) {
+        assertTrue("Applet did not start", pr.stdout.contains(APPLET_START_STRING));
+    }
+
+    public static void assertEnd(ProcessResult pr) {
+        assertTrue("Applet did not close correctly", pr.stdout.contains(APPLET_CLOSE_STRING));
+    }
+
+    public static void assertCodebaseConnection(ProcessResult pr) {
+        assertUrlCodebase(pr, true);
+        assertSocketCodebase(pr, true);
+    }
+
+    public static void assertNoCodebaseConnection(ProcessResult pr) {
+        assertUrlCodebase(pr, false);
+        assertSocketCodebase(pr, false);
+    }
+
+    public static void assertUrlCodebase(ProcessResult pr, boolean b) {
+        assertTrue(URL_CODEBASE, pr.stdout.contains(URL_CODEBASE));
+        String expected;
+        if (b) {
+            expected = URL_CODEBASE_SUCCESS;
+        } else {
+            expected = URL_CODEBASE_FAILURE;
+        }
+        assertTrue("Expected " + expected, pr.stdout.contains(expected));
+    }
+
+    public static void assertSocketCodebase(ProcessResult pr, boolean b) {
+        assertTrue(SOCKET_CODEBASE, pr.stdout.contains(SOCKET_CODEBASE));
+        String expected;
+        if (b) {
+            expected = SOCKET_CODEBASE_SUCCESS;
+        } else {
+            expected = SOCKET_CODEBASE_FAILURE;
+        }
+        assertTrue("Expected " + expected, pr.stdout.contains(expected));
+    }
+
+    public static void assertDocumentBaseConnection(ProcessResult pr) {
+        assertUrlDocumentBase(pr, true);
+        assertSocketDocumentBase(pr, true);
+    }
+
+    public static void assertNoDocumentBaseConnection(ProcessResult pr) {
+        assertUrlDocumentBase(pr, false);
+        assertSocketDocumentBase(pr, false);
+    }
+
+    public static void assertUrlDocumentBase(ProcessResult pr, boolean b) {
+        assertTrue(URL_DOCUMENTBASE, pr.stdout.contains(URL_DOCUMENTBASE));
+        String expected;
+        if (b) {
+            expected = URL_DOCUMENTBASE_SUCCESS;
+        } else {
+            expected = URL_DOCUMENTBASE_FAILURE;
+        }
+        assertTrue("Expected " + expected, pr.stdout.contains(expected));
+    }
+
+    public static void assertSocketDocumentBase(ProcessResult pr, boolean b) {
+        assertTrue(SOCKET_DOCUMENTBASE, pr.stdout.contains(SOCKET_DOCUMENTBASE));
+        String expected;
+        if (b) {
+            expected = SOCKET_DOCUMENTBASE_SUCCESS;
+        } else {
+            expected = SOCKET_DOCUMENTBASE_FAILURE;
+        }
+        assertTrue("Expected " + expected, pr.stdout.contains(expected));
+    }
+
+    public static void assertUnrelatedConnection(ProcessResult pr) {
+        assertUnrelatedUrlConnection(pr, true);
+        assertUnrelatedSocketConnection(pr, true);
+    }
+
+    public static void assertNoUnrelatedConnection(ProcessResult pr) {
+        assertUnrelatedUrlConnection(pr, false);
+        assertUnrelatedSocketConnection(pr, false);
+    }
+
+    public static void assertUnrelatedUrlConnection(ProcessResult pr, boolean b) {
+        assertTrue(URL_UNRELATED, pr.stdout.contains(URL_UNRELATED));
+        String expected;
+        if (b) {
+            expected = URL_UNRELATED_SUCCESS;
+        } else {
+            expected = URL_UNRELATED_FAILURE;
+        }
+        assertTrue("Expected " + expected, pr.stdout.contains(expected));
+    }
+
+    public static void assertUnrelatedSocketConnection(ProcessResult pr, boolean b) {
+        assertTrue(SOCKET_UNRELATED, pr.stdout.contains(SOCKET_UNRELATED));
+        String expected;
+        if (b) {
+            expected = SOCKET_UNRELATED_SUCCESS;
+        } else {
+            expected = SOCKET_UNRELATED_FAILURE;
+        }
+        assertTrue("Expected " + expected, pr.stdout.contains(expected));
+    }
+
+    @Test
+    public void testHtmlSetCode() throws Exception {
+        TemplatedHtmlDoc doc = new TemplatedHtmlDoc(server, "SOPBypass.html");
+        assertFalse("Doc should not contain \"code=\"", doc.toString().contains("code="));
+        doc.setCode("foo");
+        assertTrue("Doc should contain \"code=\"foo\"\"", doc.toString().contains("code=\"foo\""));
+    }
+
+    @Test
+    public void testHtmlSetCodeEmpty() throws Exception {
+        TemplatedHtmlDoc doc = new TemplatedHtmlDoc(server, "SOPBypass.html");
+        assertFalse("Doc should not contain \"code=\"", doc.toString().contains("code="));
+        doc.setCode("");
+        assertFalse("Doc should not contain \"code=\"", doc.toString().contains("code="));
+    }
+
+    @Test
+    public void testHtmlSetArchive() throws Exception {
+        TemplatedHtmlDoc doc = new TemplatedHtmlDoc(server, "SOPBypass.html");
+        assertFalse("Doc should not contain \"archive=\"", doc.toString().contains("archive="));
+        doc.setArchive("foo");
+        assertTrue("Doc should contain \"archive=\"foo\"\"", doc.toString().contains("archive=\"foo\""));
+    }
+
+    @Test
+    public void testHtmlSetArchiveEmpty() throws Exception {
+        TemplatedHtmlDoc doc = new TemplatedHtmlDoc(server, "SOPBypass.html");
+        assertFalse("Doc should not contain \"archive=\"", doc.toString().contains("archive="));
+        doc.setArchive("");
+        assertFalse("Doc should not contain \"archive=\"", doc.toString().contains("archive="));
+    }
+
+    @Test
+    public void testHtmlSetCodebase() throws Exception {
+        TemplatedHtmlDoc doc = new TemplatedHtmlDoc(server, "SOPBypass.html");
+        assertFalse("Doc should not contain \"codebase=\"", doc.toString().contains("codebase="));
+        doc.setCodeBase("foo");
+        assertTrue("Doc should contain \"codebase=\"foo\"\"", doc.toString().contains("codebase=\"foo\""));
+    }
+
+    @Test
+    public void testHtmlSetCodebaseEmpty() throws Exception {
+        TemplatedHtmlDoc doc = new TemplatedHtmlDoc(server, "SOPBypass.html");
+        assertFalse("Doc should not contain \"codebase=\"", doc.toString().contains("codebase="));
+        doc.setCodeBase("");
+        assertFalse("Doc should not contain \"codebase=\"", doc.toString().contains("codebase="));
+    }
+
+    public static class TemplatedHtmlDoc {
+
+        private static final String CODE_TOKEN = "CODE_REPLACEMENT_TOKEN";
+        private static final String ARCHIVE_TOKEN = "ARCHIVE_REPLACEMENT_TOKEN";
+        private static final String CODEBASE_TOKEN = "CODEBASE_REPLACEMENT_TOKEN";
+        private static final String FILENAME = "SOPBypass-filtered.html";
+        private static final String NEWLINE = System.lineSeparator();
+
+        private ServerAccess access = null;
+        private String content = null;
+
+        public TemplatedHtmlDoc(ServerAccess access, String resourceLocation) throws IOException {
+            this.access = access;
+            content = access.getResourceAsString(resourceLocation);
+        }
+
+        public void setCode(String code) {
+            if (code == null || code.isEmpty()) {
+                content = content.replaceAll(CODE_TOKEN, NEWLINE);
+            } else {
+                content = content.replaceAll(CODE_TOKEN, "code=\"" + code + "\"" + NEWLINE);
+            }
+        }
+
+        public void setArchive(String archive) {
+            if (archive == null || archive.isEmpty()) {
+                content = content.replaceAll(ARCHIVE_TOKEN, NEWLINE);
+            } else {
+                content = content.replaceAll(ARCHIVE_TOKEN, "archive=\"" + archive + "\"" + NEWLINE);
+            }
+        }
+
+        public void setCodeBase(String codeBase) {
+            if (codeBase == null || codeBase.isEmpty()) {
+                content = content.replaceAll(CODEBASE_TOKEN, NEWLINE);
+            } else {
+                content = content.replaceAll(CODEBASE_TOKEN, "codebase=\"" + codeBase + "\"" + NEWLINE);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return content;
+        }
+
+        public String getFileName() {
+            return FILENAME;
+        }
+
+        public File getLocation() {
+            return new File(access.getDir(), getFileName());
+        }
+
+        public void save() throws IOException {
+            access.saveFile(content, getLocation());
+        }
+
+    }
+
+    public static class TemplatedJnlpDoc {
+
+        private static final String DOCUMENTBASE_TOKEN = "DOCUMENTBASE_REPLACEMENT_TOKEN";
+        private static final String CODEBASE_TOKEN = "CODEBASE_REPLACEMENT_TOKEN";
+        private static final String JAR_TOKEN = "JAR_HREF_REPLACEMENT_TOKEN";
+        private static final String FILENAME = "SOPBypass-filtered.jnlp";
+
+        private ServerAccess access;
+        private String content;
+
+        public TemplatedJnlpDoc(ServerAccess access, String resourceLocation) throws IOException {
+            this.access = access;
+            content = access.getResourceAsString(resourceLocation);
+        }
+
+        public void setDocumentBase(String documentBase) {
+            String replacement;
+            if (documentBase == null || documentBase.isEmpty()) {
+                replacement = ".";
+            } else {
+                replacement = documentBase;
+            }
+            content = content.replaceAll(DOCUMENTBASE_TOKEN, replacement);
+        }
+
+        public void setCodeBase(String codeBase) {
+            String replacement;
+            if (codeBase == null || codeBase.isEmpty()) {
+                replacement = ".";
+            } else {
+                replacement = codeBase;
+            }
+            content = content.replaceAll(CODEBASE_TOKEN, replacement);
+        }
+
+        public void setJarHref(String jarHref) {
+            content = content.replaceAll(JAR_TOKEN, jarHref);
+        }
+
+        @Override
+        public String toString() {
+            return content;
+        }
+
+        public String getFileName() {
+            return FILENAME;
+        }
+
+        public File getLocation() {
+            return new File(access.getDir(), getFileName());
+        }
+
+        public void save() throws IOException {
+            access.saveFile(content, getLocation());
+        }
+
+    }
+
+}