/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 org.apache.catalina.connector;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.junit.Assert;
import org.junit.Test;

import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.SimpleHttpClient;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;

public class TestCoyoteAdapter extends TomcatBaseTest {

    public static final String TEXT_8K;
    public static final byte[] BYTES_8K;

    static {
        StringBuilder sb = new StringBuilder(8192);
        for (int i = 0; i < 512; i++) {
            sb.append("0123456789ABCDEF");
        }
        TEXT_8K = sb.toString();
        BYTES_8K = TEXT_8K.getBytes(StandardCharsets.UTF_8);
    }
    @Test
    public void testPathParmsRootNone() throws Exception {
        pathParamTest("/", "none");
    }

    @Test
    public void testPathParmsFooNone() throws Exception {
        pathParamTest("/foo", "none");
    }

    @Test
    public void testPathParmsRootSessionOnly() throws Exception {
        pathParamTest("/;jsessionid=1234", "1234");
    }

    @Test
    public void testPathParmsFooSessionOnly() throws Exception {
        pathParamTest("/foo;jsessionid=1234", "1234");
    }

    @Test
    public void testPathParmsFooSessionDummy() throws Exception {
        pathParamTest("/foo;jsessionid=1234;dummy", "1234");
    }

    @Test
    public void testPathParmsFooSessionDummyValue() throws Exception {
        pathParamTest("/foo;jsessionid=1234;dummy=5678", "1234");
    }

    @Test
    public void testPathParmsFooSessionValue() throws Exception {
        pathParamTest("/foo;jsessionid=1234;=5678", "1234");
    }

    @Test
    public void testPathParmsFooSessionBar() throws Exception {
        pathParamTest("/foo;jsessionid=1234/bar", "1234");
    }

    @Test
    public void testPathParamsRedirect() throws Exception {
        // Setup Tomcat instance
        Tomcat tomcat = getTomcatInstance();

        // Must have a real docBase. Don't use java.io.tmpdir as it may not be
        // writable.
        File docBase = new File(getTemporaryDirectory(), "testCoyoteAdapter");
        addDeleteOnTearDown(docBase);
        if (!docBase.mkdirs() && !docBase.isDirectory()) {
            Assert.fail("Failed to create: [" + docBase.toString() + "]");
        }

        // Create the folder that will trigger the redirect
        File foo = new File(docBase, "foo");
        addDeleteOnTearDown(foo);
        if (!foo.mkdirs() && !foo.isDirectory()) {
            Assert.fail("Unable to create foo directory in docBase");
        }

        Context ctx = tomcat.addContext("", docBase.getAbsolutePath());

        Tomcat.addServlet(ctx, "servlet", new PathParamServlet());
        ctx.addServletMappingDecoded("/", "servlet");

        tomcat.start();

        testPath("/", "none");
        testPath("/;jsessionid=1234", "1234");
        testPath("/foo;jsessionid=1234", "1234");
        testPath("/foo;jsessionid=1234;dummy", "1234");
        testPath("/foo;jsessionid=1234;dummy=5678", "1234");
        testPath("/foo;jsessionid=1234;=5678", "1234");
        testPath("/foo;jsessionid=1234/bar", "1234");
    }

    private void pathParamTest(String path, String expected) throws Exception {
        // Setup Tomcat instance
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        Tomcat.addServlet(ctx, "servlet", new PathParamServlet());
        ctx.addServletMappingDecoded("/", "servlet");

        tomcat.start();

        ByteChunk res = getUrl("http://localhost:" + getPort() + path);
        Assert.assertEquals(expected, res.toString());
    }

    private void testPath(String path, String expected) throws Exception {
        ByteChunk res = getUrl("http://localhost:" + getPort() + path);
        Assert.assertEquals(expected, res.toString());
    }

    private static class PathParamServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setContentType("text/plain");
            PrintWriter pw = resp.getWriter();
            String sessionId = req.getRequestedSessionId();
            if (sessionId == null) {
                sessionId = "none";
            }
            pw.write(sessionId);
        }
    }

    @Test
    public void testPathParamExtRootNoParam() throws Exception {
        pathParamExtensionTest("/testapp/blah.txt", "none");
    }

    @Test
    public void testPathParamExtLevel1NoParam() throws Exception {
        pathParamExtensionTest("/testapp/blah/blah.txt", "none");
    }

    @Test
    public void testPathParamExtLevel1WithParam() throws Exception {
        pathParamExtensionTest("/testapp/blah;x=y/blah.txt", "none");
    }

    private void pathParamExtensionTest(String path, String expected)
            throws Exception {
        // Setup Tomcat instance
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("/testapp", null);

        Tomcat.addServlet(ctx, "servlet", new PathParamServlet());
        ctx.addServletMappingDecoded("*.txt", "servlet");

        tomcat.start();

        ByteChunk res = getUrl("http://localhost:" + getPort() + path);
        Assert.assertEquals(expected, res.toString());
    }

    @Test
    public void testBug54602a() throws Exception {
        // No UTF-8
        doTestUriDecoding("/foo", "UTF-8", "/foo");
    }

    @Test
    public void testBug54602b() throws Exception {
        // Valid UTF-8
        doTestUriDecoding("/foo%c4%87", "UTF-8", "/foo\u0107");
    }

    @Test
    public void testBug54602c() throws Exception {
        // Partial UTF-8
        doTestUriDecoding("/foo%c4", "UTF-8", "/foo\uFFFD");
    }

    @Test
    public void testBug54602d() throws Exception {
        // Invalid UTF-8
        doTestUriDecoding("/foo%ff", "UTF-8", "/foo\uFFFD");
    }

    @Test
    public void testBug54602e() throws Exception {
        // Invalid UTF-8
        doTestUriDecoding("/foo%ed%a0%80", "UTF-8", "/foo\uFFFD\uFFFD\uFFFD");
    }

    private void doTestUriDecoding(String path, String encoding,
            String expectedPathInfo) throws Exception{

        // Setup Tomcat instance
        Tomcat tomcat = getTomcatInstance();

        tomcat.getConnector().setURIEncoding(encoding);

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        PathInfoServlet servlet = new PathInfoServlet();
        Tomcat.addServlet(ctx, "servlet", servlet);
        ctx.addServletMappingDecoded("/*", "servlet");

        tomcat.start();

        int rc = getUrl("http://localhost:" + getPort() + path,
                new ByteChunk(), null);
        Assert.assertEquals(HttpServletResponse.SC_OK, rc);

        Assert.assertEquals(expectedPathInfo, servlet.getPathInfo());
    }

    private static class PathInfoServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        private volatile String pathInfo = null;

        public String getPathInfo() {
            return pathInfo;
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {

            // Not thread safe. Concurrent requests to this servlet will
            // over-write all the results but the last processed.
            pathInfo = req.getPathInfo();
        }
    }


    @Test
    public void testBug54928() throws Exception {
        // Setup Tomcat instance
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        AsyncServlet servlet = new AsyncServlet();
        Wrapper w = Tomcat.addServlet(ctx, "async", servlet);
        w.setAsyncSupported(true);
        ctx.addServletMappingDecoded("/async", "async");

        tomcat.start();

        SimpleHttpClient client = new SimpleHttpClient() {
            @Override
            public boolean isResponseBodyOK() {
                return true;
            }
        };

        String request = "GET /async HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: a" + SimpleHttpClient.CRLF + SimpleHttpClient.CRLF;

        client.setPort(getPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.sendRequest();

        for (int i = 0; i < 10; i++) {
            String line = client.readLine();
            if (line != null && line.length() > 20) {
                log.info(line.subSequence(0, 20) + "...");
            }
        }

        client.disconnect();

        // Wait for server thread to stop
        Thread t = servlet.getThread();
        long startTime = System.nanoTime();
        t.join(5000);
        long endTime = System.nanoTime();
        log.info("Waited for servlet thread to stop for "
                + (endTime - startTime) / 1000000 + " ms");

        Assert.assertTrue(servlet.isCompleted());
    }

    @Test
    public void testNormalize01() {
        doTestNormalize("/foo/../bar", "/bar");
    }

    private void doTestNormalize(String input, String expected) {
        MessageBytes mb = MessageBytes.newInstance();
        byte[] b = input.getBytes(StandardCharsets.UTF_8);
        mb.setBytes(b, 0, b.length);

        boolean result = CoyoteAdapter.normalize(mb);
        mb.toString();

        if (expected == null) {
            Assert.assertFalse(result);
        } else {
            Assert.assertTrue(result);
            Assert.assertEquals(expected, mb.toString());
        }
    }


    private class AsyncServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        // This is a hack that won't work generally as servlets are expected to
        // handle more than one request.
        private Thread t;
        private volatile boolean completed = false;

        public Thread getThread() {
            return t;
        }

        public boolean isCompleted() {
            return completed;
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {

            resp.setContentType("text/plain");
            resp.setCharacterEncoding("UTF-8");

            final OutputStream os = resp.getOutputStream();

            final AsyncContext asyncCtxt = req.startAsync();
            asyncCtxt.setTimeout(3000);

            t = new Thread(new Runnable() {

                @Override
                public void run() {
                    for (int i = 0; i < 20; i++) {
                        try {
                            // Some tests depend on this write failing (e.g.
                            // because the client has gone away). In some cases
                            // there may be a large (ish) buffer to fill before
                            // the write fails.
                            for (int j = 0 ; j < 8; j++) {
                                os.write(BYTES_8K);
                            }
                            os.flush();
                            Thread.sleep(1000);
                        } catch (Exception e) {
                            log.info("Exception caught " + e);
                            try {
                                // Note if request times out before this
                                // exception is thrown and the complete call
                                // below is made, the complete call below will
                                // fail since the timeout will have completed
                                // the request.
                                asyncCtxt.complete();
                                break;
                            } finally {
                                completed = true;
                            }
                        }
                    }
                }
            });
            t.setName("testBug54928");
            t.start();
        }
    }
}
