@Test
  public void testGzip() throws Exception {
    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File file0 = new File(resBase, "data0.txt");
    createFile(file0, "Hello Text 0");
    File file0gz = new File(resBase, "data0.txt.gz");
    createFile(file0gz, "fake gzip");

    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("dirAllowed", "false");
    defholder.setInitParameter("redirectWelcome", "false");
    defholder.setInitParameter("welcomeServlets", "false");
    defholder.setInitParameter("gzip", "true");
    defholder.setInitParameter("resourceBase", resBasePath);

    String response =
        connector.getResponses("GET /context/data0.txt HTTP/1.0\r\nHost:localhost:8080\r\n\r\n");
    assertResponseContains("Content-Length: 12", response);
    assertResponseContains("Hello Text 0", response);
    assertResponseContains("Vary: Accept-Encoding", response);
    assertResponseNotContains("Content-Encoding: gzip", response);

    response =
        connector.getResponses(
            "GET /context/data0.txt HTTP/1.0\r\nHost:localhost:8080\r\nAccept-Encoding:gzip\r\n\r\n");
    assertResponseContains("Content-Length: 9", response);
    assertResponseContains("fake gzip", response);
    assertResponseContains("Vary: Accept-Encoding", response);
    assertResponseContains("Content-Encoding: gzip", response);
  }
  @Test
  public void testResourceBase() throws Exception {
    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File foobar = new File(resBase, "foobar.txt");
    File link = new File(resBase, "link.txt");
    createFile(foobar, "Foo Bar");

    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("resourceBase", resBasePath);
    defholder.setInitParameter("gzip", "false");

    String response;

    response = connector.getResponses("GET /context/foobar.txt HTTP/1.0\r\n\r\n");
    assertResponseContains("Foo Bar", response);

    if (!OS.IS_WINDOWS) {
      Files.createSymbolicLink(link.toPath(), foobar.toPath());
      response = connector.getResponses("GET /context/link.txt HTTP/1.0\r\n\r\n");
      assertResponseContains("404", response);

      context.addAliasCheck(new ContextHandler.ApproveAliases());

      response = connector.getResponses("GET /context/link.txt HTTP/1.0\r\n\r\n");
      assertResponseContains("Foo Bar", response);
    }
  }
  @Before
  public void init() throws Exception {
    server = new Server();

    connector = new LocalConnector(server);
    connector
        .getConnectionFactory(HttpConfiguration.ConnectionFactory.class)
        .getHttpConfiguration()
        .setSendServerVersion(false);

    context = new ServletContextHandler();
    context.setContextPath("/context");
    context.setWelcomeFiles(new String[] {"index.html", "index.jsp", "index.htm"});

    server.setHandler(context);
    server.addConnector(connector);

    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File data = new File(resBase, "data.txt");
    createFile(data, DATA);
    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("acceptRanges", "true");
    defholder.setInitParameter("resourceBase", resBasePath);

    server.start();
  }
 private void deleteFile(File file) throws IOException {
   if (OS.IS_WINDOWS) {
     // Windows doesn't seem to like to delete content that was recently created
     // Attempt a delete and if it fails, attempt a rename
     boolean deleted = file.delete();
     if (!deleted) {
       File deletedDir = MavenTestingUtils.getTargetFile(".deleted");
       FS.ensureDirExists(deletedDir);
       File dest = File.createTempFile(file.getName(), "deleted", deletedDir);
       boolean renamed = file.renameTo(dest);
       if (!renamed)
         System.err.println("WARNING: unable to move file out of the way: " + file.getName());
     }
   } else {
     Assert.assertTrue("Deleting: " + file.getName(), file.delete());
   }
 }
  @Test
  public void testWelcomeExactServlet() throws Exception {
    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File inde = new File(resBase, "index.htm");
    File index = new File(resBase, "index.html");

    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("dirAllowed", "false");
    defholder.setInitParameter("redirectWelcome", "false");
    defholder.setInitParameter("welcomeServlets", "exact");
    defholder.setInitParameter("gzip", "false");
    defholder.setInitParameter("resourceBase", resBasePath);

    ServletHolder jspholder = context.addServlet(NoJspServlet.class, "*.jsp");
    context.addServlet(jspholder, "/index.jsp");

    String response;

    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("JSP support not configured", response);

    createFile(index, "<h1>Hello Index</h1>");
    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("<h1>Hello Index</h1>", response);

    createFile(inde, "<h1>Hello Inde</h1>");
    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("<h1>Hello Index</h1>", response);

    // In Windows it's impossible to delete files that are somehow in use
    // Avoid to fail the test if we're on Windows
    if (!OS.IS_WINDOWS) {
      deleteFile(index);
      response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
      assertResponseContains("<h1>Hello Inde</h1>", response);

      deleteFile(inde);
      response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
      assertResponseContains("JSP support not configured", response);
    }
  }
  @Test
  public void testWelcome() throws Exception {
    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File inde = new File(resBase, "index.htm");
    File index = new File(resBase, "index.html");

    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("dirAllowed", "false");
    defholder.setInitParameter("redirectWelcome", "false");
    defholder.setInitParameter("welcomeServlets", "false");
    defholder.setInitParameter("gzip", "false");
    defholder.setInitParameter("resourceBase", resBasePath);
    defholder.setInitParameter("maxCacheSize", "1024000");
    defholder.setInitParameter("maxCachedFileSize", "512000");
    defholder.setInitParameter("maxCachedFiles", "100");

    @SuppressWarnings("unused")
    ServletHolder jspholder = context.addServlet(NoJspServlet.class, "*.jsp");

    String response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("403", response);

    createFile(index, "<h1>Hello Index</h1>");
    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("<h1>Hello Index</h1>", response);

    createFile(inde, "<h1>Hello Inde</h1>");
    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("<h1>Hello Index</h1>", response);

    assertTrue(index.delete());
    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("<h1>Hello Inde</h1>", response);

    assertTrue(inde.delete());
    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("403", response);
  }
  @Test
  public void testListingXSS() throws Exception {
    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/*");
    defholder.setInitParameter("dirAllowed", "true");
    defholder.setInitParameter("redirectWelcome", "false");
    defholder.setInitParameter("gzip", "false");

    testdir.ensureEmpty();

    /* create some content in the docroot */
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    assertTrue(new File(resBase, "one").mkdir());
    assertTrue(new File(resBase, "two").mkdir());
    assertTrue(new File(resBase, "three").mkdir());
    if (!OS.IS_WINDOWS) {
      assertTrue(
          "Creating dir 'f??r' (Might not work in Windows)", new File(resBase, "f??r").mkdir());
    }

    String resBasePath = resBase.getAbsolutePath();
    defholder.setInitParameter("resourceBase", resBasePath);

    StringBuffer req1 = new StringBuffer();
    /*
     * Intentionally bad request URI. Sending a non-encoded URI with typically encoded characters '<', '>', and
     * '"'.
     */
    req1.append("GET /context/;<script>window.alert(\"hi\");</script> HTTP/1.0\n");
    req1.append("\n");

    String response = connector.getResponses(req1.toString());

    assertResponseContains("/one/", response);
    assertResponseContains("/two/", response);
    assertResponseContains("/three/", response);
    if (!OS.IS_WINDOWS) {
      assertResponseContains("/f%3F%3Fr", response);
    }

    assertResponseNotContains("<script>", response);
  }
  @Test
  public void testFiltered() throws Exception {
    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File file0 = new File(resBase, "data0.txt");
    createFile(file0, "Hello Text 0");

    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("dirAllowed", "false");
    defholder.setInitParameter("redirectWelcome", "false");
    defholder.setInitParameter("welcomeServlets", "false");
    defholder.setInitParameter("gzip", "false");
    defholder.setInitParameter("resourceBase", resBasePath);

    String response = connector.getResponses("GET /context/data0.txt HTTP/1.0\r\n\r\n");
    assertResponseContains("Content-Length: 12", response);
    assertResponseNotContains("Extra Info", response);

    context.addFilter(OutputFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
    response = connector.getResponses("GET /context/data0.txt HTTP/1.0\r\n\r\n");
    assertResponseContains("Content-Length: 2", response); // 20 something long
    assertResponseContains("Extra Info", response);
    assertResponseNotContains("Content-Length: 12", response);

    context.getServletHandler().setFilterMappings(new FilterMapping[] {});
    context.getServletHandler().setFilters(new FilterHolder[] {});

    context.addFilter(WriterFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
    response = connector.getResponses("GET /context/data0.txt HTTP/1.0\r\n\r\n");
    assertResponseContains("Content-Length: 2", response); // 20 something long
    assertResponseContains("Extra Info", response);
    assertResponseNotContains("Content-Length: 12", response);
  }
  @BeforeClass
  public static void startServer() throws Exception {
    server = new Server();
    ServerConnector connector = new ServerConnector(server);
    connector.setPort(0);
    server.addConnector(connector);

    ContextHandlerCollection contexts = new ContextHandlerCollection();

    File dir =
        MavenTestingUtils.getTargetTestingDir(ResourceHandlerRangeTest.class.getSimpleName());
    FS.ensureEmpty(dir);
    File rangeFile = new File(dir, "range.txt");
    try (FileWriter writer = new FileWriter(rangeFile)) {
      writer.append("0123456789");
      writer.flush();
    }

    ContextHandler contextHandler = new ContextHandler();
    ResourceHandler contentResourceHandler = new ResourceHandler();
    contextHandler.setBaseResource(Resource.newResource(dir.getAbsolutePath()));
    contextHandler.setHandler(contentResourceHandler);
    contextHandler.setContextPath("/");

    contexts.addHandler(contextHandler);

    server.setHandler(contexts);
    server.start();

    String host = connector.getHost();
    if (host == null) {
      host = "localhost";
    }
    int port = connector.getLocalPort();
    serverUri = new URI(String.format("http://%s:%d/", host, port));
  }
  public void testIfETag(String content) throws Exception {
    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File file = new File(resBase, "file.txt");

    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("resourceBase", resBasePath);
    defholder.setInitParameter("maxCacheSize", "4096");
    defholder.setInitParameter("maxCachedFileSize", "25");
    defholder.setInitParameter("maxCachedFiles", "100");
    defholder.setInitParameter("etags", "true");

    String response;

    createFile(file, content);
    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\n\r\n");

    assertResponseContains("200", response);
    assertResponseContains("ETag", response);
    String etag = getHeaderValue("ETag", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-None-Match: "
                + etag
                + "\r\n\r\n");
    assertResponseContains("304", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-None-Match: wibble,"
                + etag
                + ",wobble\r\n\r\n");
    assertResponseContains("304", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-None-Match: wibble\r\n\r\n");
    assertResponseContains("200", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-None-Match: wibble, wobble\r\n\r\n");
    assertResponseContains("200", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Match: "
                + etag
                + "\r\n\r\n");
    assertResponseContains("200", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Match: wibble,"
                + etag
                + ",wobble\r\n\r\n");
    assertResponseContains("200", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Match: wibble\r\n\r\n");
    assertResponseContains("412", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Match: wibble, wobble\r\n\r\n");
    assertResponseContains("412", response);
  }
  public void testIfModified(String content) throws Exception {
    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File file = new File(resBase, "file.txt");

    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("resourceBase", resBasePath);
    defholder.setInitParameter("maxCacheSize", "4096");
    defholder.setInitParameter("maxCachedFileSize", "25");
    defholder.setInitParameter("maxCachedFiles", "100");

    String response = connector.getResponses("GET /context/file.txt HTTP/1.0\r\n\r\n");
    assertResponseContains("404", response);

    createFile(file, content);
    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\n\r\n");

    assertResponseContains("200", response);
    assertResponseContains("Last-Modified", response);
    String last_modified = getHeaderValue("Last-Modified", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Modified-Since: "
                + last_modified
                + "\r\n\r\n");
    assertResponseContains("304", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Modified-Since: "
                + HttpFields.formatDate(System.currentTimeMillis() - 10000)
                + "\r\n\r\n");
    assertResponseContains("200", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Modified-Since: "
                + HttpFields.formatDate(System.currentTimeMillis() + 10000)
                + "\r\n\r\n");
    assertResponseContains("304", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Unmodified-Since: "
                + HttpFields.formatDate(System.currentTimeMillis() + 10000)
                + "\r\n\r\n");
    assertResponseContains("200", response);

    response =
        connector.getResponses(
            "GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Unmodified-Since: "
                + HttpFields.formatDate(System.currentTimeMillis() - 10000)
                + "\r\n\r\n");
    assertResponseContains("412", response);
  }
  @Test
  public void testRangeRequests() throws Exception {
    testdir.ensureEmpty();
    File resBase = testdir.getFile("docroot");
    FS.ensureDirExists(resBase);
    File data = new File(resBase, "data.txt");
    createFile(
        data, "01234567890123456789012345678901234567890123456789012345678901234567890123456789");
    String resBasePath = resBase.getAbsolutePath();

    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("dirAllowed", "false");
    defholder.setInitParameter("redirectWelcome", "false");
    defholder.setInitParameter("welcomeServlets", "false");
    defholder.setInitParameter("gzip", "false");
    defholder.setInitParameter("acceptRanges", "true");
    defholder.setInitParameter("resourceBase", resBasePath);

    String response =
        connector.getResponses(
            "GET /context/data.txt HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n\r\n");
    assertResponseContains("200 OK", response);
    assertResponseContains("Accept-Ranges: bytes", response);

    response =
        connector.getResponses(
            "GET /context/data.txt HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n"
                + "Range: bytes=0-9\r\n"
                + "\r\n");
    assertResponseContains("206 Partial", response);
    assertResponseContains("Content-Type: text/plain", response);
    assertResponseContains("Content-Length: 10", response);
    assertResponseContains("Content-Range: bytes 0-9/80", response);

    response =
        connector.getResponses(
            "GET /context/data.txt HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n"
                + "Range: bytes=0-9,20-29,40-49\r\n"
                + "\r\n");
    int start = response.indexOf("--jetty");
    String body = response.substring(start);
    String boundary = body.substring(0, body.indexOf("\r\n"));
    assertResponseContains("206 Partial", response);
    assertResponseContains("Content-Type: multipart/byteranges; boundary=", response);
    assertResponseContains("Content-Range: bytes 0-9/80", response);
    assertResponseContains("Content-Range: bytes 20-29/80", response);
    assertResponseContains("Content-Length: " + body.length(), response);
    assertTrue(body.endsWith(boundary + "--\r\n"));

    response =
        connector.getResponses(
            "GET /context/data.txt HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n"
                + "Range: bytes=0-9,20-29,40-49,70-79\r\n"
                + "\r\n");
    start = response.indexOf("--jetty");
    body = response.substring(start);
    boundary = body.substring(0, body.indexOf("\r\n"));
    assertResponseContains("206 Partial", response);
    assertResponseContains("Content-Type: multipart/byteranges; boundary=", response);
    assertResponseContains("Content-Range: bytes 0-9/80", response);
    assertResponseContains("Content-Range: bytes 20-29/80", response);
    assertResponseContains("Content-Range: bytes 70-79/80", response);
    assertResponseContains("Content-Length: " + body.length(), response);
    assertTrue(body.endsWith(boundary + "--\r\n"));

    response =
        connector.getResponses(
            "GET /context/data.txt HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n"
                + "Range: bytes=0-9,20-29,40-49,60-60,70-79\r\n"
                + "\r\n");
    start = response.indexOf("--jetty");
    body = response.substring(start);
    boundary = body.substring(0, body.indexOf("\r\n"));
    assertResponseContains("206 Partial", response);
    assertResponseContains("Content-Type: multipart/byteranges; boundary=", response);
    assertResponseContains("Content-Range: bytes 0-9/80", response);
    assertResponseContains("Content-Range: bytes 20-29/80", response);
    assertResponseContains("Content-Range: bytes 60-60/80", response);
    assertResponseContains("Content-Range: bytes 70-79/80", response);
    assertResponseContains("Content-Length: " + body.length(), response);
    assertTrue(body.endsWith(boundary + "--\r\n"));

    // test a range request with a file with no suffix, therefore no mimetype

    File nofilesuffix = new File(resBase, "nofilesuffix");
    createFile(
        nofilesuffix,
        "01234567890123456789012345678901234567890123456789012345678901234567890123456789");

    response =
        connector.getResponses(
            "GET /context/nofilesuffix HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n"
                + "\r\n");
    assertResponseContains("200 OK", response);
    assertResponseContains("Accept-Ranges: bytes", response);

    response =
        connector.getResponses(
            "GET /context/nofilesuffix HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n"
                + "Range: bytes=0-9\r\n"
                + "\r\n");
    assertResponseContains("206 Partial", response);
    assertResponseContains("Content-Length: 10", response);
    assertTrue(!response.contains("Content-Type:"));
    assertResponseContains("Content-Range: bytes 0-9/80", response);

    response =
        connector.getResponses(
            "GET /context/nofilesuffix HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n"
                + "Range: bytes=0-9,20-29,40-49\r\n"
                + "\r\n");
    start = response.indexOf("--jetty");
    body = response.substring(start);
    boundary = body.substring(0, body.indexOf("\r\n"));
    assertResponseContains("206 Partial", response);
    assertResponseContains("Content-Type: multipart/byteranges; boundary=", response);
    assertResponseContains("Content-Range: bytes 0-9/80", response);
    assertResponseContains("Content-Range: bytes 20-29/80", response);
    assertResponseContains("Content-Length: " + body.length(), response);
    assertTrue(body.endsWith(boundary + "--\r\n"));

    response =
        connector.getResponses(
            "GET /context/nofilesuffix HTTP/1.1\r\n"
                + "Host: localhost\r\n"
                + "Connection: close\r\n"
                + "Range: bytes=0-9,20-29,40-49,60-60,70-79\r\n"
                + "\r\n");
    start = response.indexOf("--jetty");
    body = response.substring(start);
    boundary = body.substring(0, body.indexOf("\r\n"));
    assertResponseContains("206 Partial", response);
    assertResponseContains("Content-Type: multipart/byteranges; boundary=", response);
    assertResponseContains("Content-Range: bytes 0-9/80", response);
    assertResponseContains("Content-Range: bytes 20-29/80", response);
    assertResponseContains("Content-Range: bytes 60-60/80", response);
    assertResponseContains("Content-Range: bytes 70-79/80", response);
    assertResponseContains("Content-Length: " + body.length(), response);
    assertTrue(body.endsWith(boundary + "--\r\n"));
  }
  @Test
  public void testListingContextBreakout() throws Exception {
    ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
    defholder.setInitParameter("dirAllowed", "true");
    defholder.setInitParameter("redirectWelcome", "false");
    defholder.setInitParameter("gzip", "false");
    defholder.setInitParameter("aliases", "true");

    testdir.ensureEmpty();

    /* create some content in the docroot */
    File resBase = testdir.getFile("docroot");
    assertTrue(resBase.mkdirs());

    File index = new File(resBase, "index.html");
    createFile(index, "<h1>Hello Index</h1>");

    File wackyDir = new File(resBase, "dir?");
    if (!OS.IS_WINDOWS) {
      FS.ensureDirExists(wackyDir);
    }

    wackyDir = new File(resBase, "dir;");
    assertTrue(wackyDir.mkdirs());

    /* create some content outside of the docroot */
    File sekret = testdir.getFile("sekret");
    assertTrue(sekret.mkdirs());
    File pass = new File(sekret, "pass");
    createFile(pass, "Sssh, you shouldn't be seeing this");

    /* At this point we have the following
     * testListingContextBreakout/
     * |-- docroot
     * |   |-- index.html
     * |   |-- dir?
     * |   |-- dir;
     * `-- sekret
     *     `-- pass
     */

    String resBasePath = resBase.getAbsolutePath();
    defholder.setInitParameter("resourceBase", resBasePath);

    String response;

    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("<h1>Hello Index</h1>", response);

    response = connector.getResponses("GET /context/dir?/ HTTP/1.0\r\n\r\n");
    assertResponseContains("404", response);

    if (!OS.IS_WINDOWS) {
      response = connector.getResponses("GET /context/dir%3F/ HTTP/1.0\r\n\r\n");
      assertResponseContains("Directory: /context/dir?/<", response);
    } else assertResponseContains("404", response);

    response = connector.getResponses("GET /context/index.html HTTP/1.0\r\n\r\n");
    assertResponseContains("Hello Index", response);

    response = connector.getResponses("GET /context/dir%3F/../index.html HTTP/1.0\r\n\r\n");
    assertResponseContains("Hello Index", response);

    response = connector.getResponses("GET /context/dir%3F/../../ HTTP/1.0\r\n\r\n");
    assertResponseNotContains("Directory: ", response);

    response = connector.getResponses("GET /context/dir%3F/../../sekret/pass HTTP/1.0\r\n\r\n");
    assertResponseNotContains("Sssh", response);

    response = connector.getResponses("GET /context/dir?/../../ HTTP/1.0\r\n\r\n");
    assertResponseNotContains("Directory: ", response);

    response = connector.getResponses("GET /context/dir?/../../sekret/pass HTTP/1.0\r\n\r\n");
    assertResponseNotContains("Sssh", response);

    response = connector.getResponses("GET /context/ HTTP/1.0\r\n\r\n");
    assertResponseContains("<h1>Hello Index</h1>", response);

    response = connector.getResponses("GET /context/dir;/ HTTP/1.0\r\n\r\n");
    assertResponseContains("404", response);

    response = connector.getResponses("GET /context/dir%3B/ HTTP/1.0\r\n\r\n");
    assertResponseContains("Directory: /context/dir;/<", response);

    response = connector.getResponses("GET /context/index.html HTTP/1.0\r\n\r\n");
    assertResponseContains("Hello Index", response);

    response = connector.getResponses("GET /context/dir%3B/../index.html HTTP/1.0\r\n\r\n");
    assertResponseContains("Hello Index", response);

    response = connector.getResponses("GET /context/dir%3B/../../ HTTP/1.0\r\n\r\n");
    assertResponseNotContains("Directory: ", response);

    response = connector.getResponses("GET /context/dir%3B/../../sekret/pass HTTP/1.0\r\n\r\n");
    assertResponseNotContains("Sssh", response);

    response = connector.getResponses("GET /context/dir;/../../ HTTP/1.0\r\n\r\n");
    assertResponseNotContains("Directory: ", response);

    response = connector.getResponses("GET /context/dir;/../../sekret/pass HTTP/1.0\r\n\r\n");
    assertResponseNotContains("Sssh", response);
  }