/*
 *  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.jk.common;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.CharConversionException;
import java.net.InetAddress;
import java.util.Properties;

import org.apache.coyote.Request;
import org.apache.coyote.RequestInfo;
import org.apache.coyote.Response;
import org.apache.coyote.Constants;
import org.apache.jk.core.JkHandler;
import org.apache.jk.core.Msg;
import org.apache.jk.core.MsgContext;
import org.apache.jk.core.WorkerEnv;
import org.apache.jk.core.JkChannel;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.HexUtils;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.net.SSLSupport;
import org.apache.tomcat.util.threads.ThreadWithAttributes;

/**
 * Handle messages related with basic request information.
 *
 * This object can handle the following incoming messages:
 * - "FORWARD_REQUEST" input message ( sent when a request is passed from the
 *   web server )
 * - "RECEIVE_BODY_CHUNK" input ( sent by container to pass more body, in
 *   response to GET_BODY_CHUNK )
 *
 * It can handle the following outgoing messages:
 * - SEND_HEADERS. Pass the status code and headers.
 * - SEND_BODY_CHUNK. Send a chunk of body
 * - GET_BODY_CHUNK. Request a chunk of body data
 * - END_RESPONSE. Notify the end of a request processing.
 *
 * @author Henri Gomez [hgomez@apache.org]
 * @author Dan Milstein [danmil@shore.net]
 * @author Keith Wannamaker [Keith@Wannamaker.org]
 * @author Costin Manolache
 */
public class HandlerRequest extends JkHandler
{
    private static org.apache.commons.logging.Log log=
        org.apache.commons.logging.LogFactory.getLog( HandlerRequest.class );

    /*
     * Note for Host parsing.
     */
    public static final int HOSTBUFFER = 10;

    /**
     * Thread lock.
     */
    private static Object lock = new Object();

    private HandlerDispatch dispatch;
    private String ajpidDir="conf";
    

    public HandlerRequest() {
    }

    public void init() {
        dispatch=(HandlerDispatch)wEnv.getHandler( "dispatch" );
        if( dispatch != null ) {
            // register incoming message handlers
            dispatch.registerMessageType( AjpConstants.JK_AJP13_FORWARD_REQUEST,
                                          "JK_AJP13_FORWARD_REQUEST",
                                          this, null); // 2
            
            dispatch.registerMessageType( AjpConstants.JK_AJP13_SHUTDOWN,
                                          "JK_AJP13_SHUTDOWN",
                                          this, null); // 7
            
            dispatch.registerMessageType( AjpConstants.JK_AJP13_CPING_REQUEST,
                                          "JK_AJP13_CPING_REQUEST",
                                           this, null); // 10
            dispatch.registerMessageType( HANDLE_THREAD_END,
                                         "HANDLE_THREAD_END",
                                         this, null);
            // register outgoing messages handler
            dispatch.registerMessageType( AjpConstants.JK_AJP13_SEND_BODY_CHUNK, // 3
                                          "JK_AJP13_SEND_BODY_CHUNK",
                                          this,null );
        }

        tmpBufNote=wEnv.getNoteId( WorkerEnv.ENDPOINT_NOTE, "tmpBuf" );
        secretNote=wEnv.getNoteId( WorkerEnv.ENDPOINT_NOTE, "secret" );
        
        if( next==null )
            next=wEnv.getHandler( "container" );
        if( log.isDebugEnabled() )
            log.debug( "Container handler " + next + " " + next.getName() +
                       " " + next.getClass().getName());

        // should happen on start()
        generateAjp13Id();
    }

    public void setSecret( String s ) {
        requiredSecret=s;
    }

    public void setUseSecret( boolean b ) {
        if(b) {
            requiredSecret=Double.toString(Math.random());
        }
    }

    public void setDecodedUri( boolean b ) {
        decoded=b;
    }

    public boolean isTomcatAuthentication() {
        return tomcatAuthentication;
    }

    public void setShutdownEnabled(boolean se) {
        shutdownEnabled = se;
    }

    public boolean getShutdownEnabled() {
        return shutdownEnabled;
    }

    public void setTomcatAuthentication(boolean newTomcatAuthentication) {
        tomcatAuthentication = newTomcatAuthentication;
    }
    
    public void setAjpidDir( String path ) {
        if( "".equals( path ) ) path=null;
        ajpidDir=path;
    }

    /**
     * Set the flag to tell if we JMX register requests.
     */
    public void setRegisterRequests(boolean srr) {
        registerRequests = srr;
    }

    /**
     * Get the flag to tell if we JMX register requests.
     */
    public boolean getRegisterRequests() {
        return registerRequests;
    }

    /**
     * Set the flag to delay the initial body read
     */
    public void setDelayInitialRead(boolean dir) {
	delayInitialRead = dir;
    }

    /**
     * Get the flag to tell if we delay the initial body read
     */
    public boolean getDelayInitialRead() {
	return delayInitialRead;
    }

    // -------------------- Ajp13.id --------------------

    private void generateAjp13Id() {
        int portInt=8009; // tcpCon.getPort();
        InetAddress address=null; // tcpCon.getAddress();

        if( requiredSecret == null || !shutdownEnabled )
            return;
        
        File f1=new File( wEnv.getJkHome() );
        File f2=new File( f1, "conf" );
        
        if( ! f2.exists() ) {
            log.error( "No conf dir for ajp13.id " + f2 );
            return;
        }
        
        File sf=new File( f2, "ajp13.id");
        
        if( log.isDebugEnabled())
            log.debug( "Using stop file: "+sf);

        try {
            Properties props=new Properties();

            props.put( "port", Integer.toString( portInt ));
            if( address!=null ) {
                props.put( "address", address.getHostAddress() );
            }
            if( requiredSecret !=null ) {
                props.put( "secret", requiredSecret );
            }

            FileOutputStream stopF=new FileOutputStream( sf );
            props.store( stopF, "Automatically generated, don't edit" );
        } catch( IOException ex ) {
            if(log.isDebugEnabled())
                log.debug( "Can't create stop file: "+sf,ex );
        }
    }
    
    // -------------------- Incoming message --------------------
    private String requiredSecret=null;
    private int secretNote;
    private int tmpBufNote;

    private boolean decoded=true;
    private boolean tomcatAuthentication=true;
    private boolean registerRequests=true;
    private boolean shutdownEnabled=false;
    private boolean delayInitialRead = true;
    
    public int invoke(Msg msg, MsgContext ep ) 
        throws IOException    {
        int type=msg.getByte();
        ThreadWithAttributes twa = null;
        if (Thread.currentThread() instanceof ThreadWithAttributes) {
            twa = (ThreadWithAttributes) Thread.currentThread();
        }
        Object control=ep.getControl();
        MessageBytes tmpMB=(MessageBytes)ep.getNote( tmpBufNote );
        if( tmpMB==null ) {
            tmpMB= MessageBytes.newInstance();
            ep.setNote( tmpBufNote, tmpMB);
        }

        if( log.isDebugEnabled() )
            log.debug( "Handling " + type );
        
        switch( type ) {
        case AjpConstants.JK_AJP13_FORWARD_REQUEST:
            try {
                if (twa != null) {
                    twa.setCurrentStage(control, "JkDecode");
                }
                decodeRequest( msg, ep, tmpMB );
                if (twa != null) {
                    twa.setCurrentStage(control, "JkService");
                    twa.setParam(control,
                                 ((Request)ep.getRequest()).unparsedURI());
                }
            } catch( Exception ex ) {
                /* If we are here it is because we have a bad header or something like that */
                log.error( "Error decoding request ", ex );
                msg.dump( "Incomming message");
                Response res=ep.getRequest().getResponse();
                if ( res==null ) {
                    res=new Response();
                    ep.getRequest().setResponse(res);
                }
                res.setMessage("Bad Request");
                res.setStatus(400);
                return ERROR;
            }

            if( requiredSecret != null ) {
                String epSecret=(String)ep.getNote( secretNote );
                if( epSecret==null || ! requiredSecret.equals( epSecret ) )
                    return ERROR;
            }
            /* XXX it should be computed from request, by workerEnv */
            if(log.isDebugEnabled() )
                log.debug("Calling next " + next.getName() + " " +
                  next.getClass().getName());

            int err= next.invoke( msg, ep );
            if (twa != null) {
                twa.setCurrentStage(control, "JkDone");
            }

            if( log.isDebugEnabled() )
                log.debug( "Invoke returned " + err );
            return err;
        case AjpConstants.JK_AJP13_SHUTDOWN:
            String epSecret=null;
            if( msg.getLen() > 3 ) {
                // we have a secret
                msg.getBytes( tmpMB );
                epSecret=tmpMB.toString();
            }
            
            if( requiredSecret != null &&
                requiredSecret.equals( epSecret ) ) {
                if( log.isDebugEnabled() )
                    log.debug("Received wrong secret, no shutdown ");
                return ERROR;
            }

            // XXX add isSameAddress check
            JkChannel ch=ep.getSource();
            if( !ch.isSameAddress(ep) ) {
                log.error("Shutdown request not from 'same address' ");
                return ERROR;
            }

            if( !shutdownEnabled ) {
                log.warn("Ignoring shutdown request: shutdown not enabled");
                return ERROR;
            }
            // forward to the default handler - it'll do the shutdown
            checkRequest(ep);
            next.invoke( msg, ep );

            if(log.isInfoEnabled())
                log.info("Exiting");
            System.exit(0);
            
            return OK;

            // We got a PING REQUEST, quickly respond with a PONG
        case AjpConstants.JK_AJP13_CPING_REQUEST:
            msg.reset();
            msg.appendByte(AjpConstants.JK_AJP13_CPONG_REPLY);
            ep.getSource().send( msg, ep );
            ep.getSource().flush( msg, ep ); // Server needs to get it
            return OK;

        case HANDLE_THREAD_END:
            return OK;

        default:
            if(log.isInfoEnabled())
                log.info("Unknown message " + type);
        }

        return OK;
    }

    static int count = 0;

    private Request checkRequest(MsgContext ep) {
        Request req=ep.getRequest();
        if( req==null ) {
            req=new Request();
            Response res=new Response();
            req.setResponse(res);
            ep.setRequest( req );
            if( registerRequests ) {
                synchronized(lock) {
                    ep.getSource().registerRequest(req, ep, count++);
                }
            }
        }
        return req;
    }

    private int decodeRequest( Msg msg, MsgContext ep, MessageBytes tmpMB )
        throws IOException    {
        // FORWARD_REQUEST handler
        Request req = checkRequest(ep);

        RequestInfo rp = req.getRequestProcessor();
        rp.setStage(Constants.STAGE_PARSE);
        MessageBytes tmpMB2 = (MessageBytes)req.getNote(WorkerEnv.SSL_CERT_NOTE);
        if(tmpMB2 != null) {
            tmpMB2.recycle();
        }
        req.setStartTime(System.currentTimeMillis());
        
        // Translate the HTTP method code to a String.
        byte methodCode = msg.getByte();
        if (methodCode != AjpConstants.SC_M_JK_STORED) {
            String mName=AjpConstants.methodTransArray[(int)methodCode - 1];
            req.method().setString(mName);
        }

        msg.getBytes(req.protocol()); 
        msg.getBytes(req.requestURI());

        msg.getBytes(req.remoteAddr());
        msg.getBytes(req.remoteHost());
        msg.getBytes(req.localName());
        req.setLocalPort(msg.getInt());

        boolean isSSL = msg.getByte() != 0;
        if( isSSL ) {
            // XXX req.setSecure( true );
            req.scheme().setString("https");
        }

        decodeHeaders( ep, msg, req, tmpMB );

        decodeAttributes( ep, msg, req, tmpMB );

        rp.setStage(Constants.STAGE_PREPARE);
        MessageBytes valueMB = req.getMimeHeaders().getValue("host");
        parseHost(valueMB, req);
        // set cookies on request now that we have all headers
        req.getCookies().setHeaders(req.getMimeHeaders());

        // Check to see if there should be a body packet coming along
        // immediately after
        long cl=req.getContentLengthLong();
        if(cl > 0) {
            JkInputStream jkIS = ep.getInputStream();
            jkIS.setIsReadRequired(true);
            if(!delayInitialRead) {
                jkIS.receive();
            }
        }
    
        if (log.isTraceEnabled()) {
            log.trace(req.toString());
         }

        return OK;
    }
        
    private int decodeAttributes( MsgContext ep, Msg msg, Request req,
                                  MessageBytes tmpMB) {
        boolean moreAttr=true;

        while( moreAttr ) {
            byte attributeCode=msg.getByte();
            if( attributeCode == AjpConstants.SC_A_ARE_DONE )
                return 200;

            /* Special case ( XXX in future API make it separate type !)
             */
            if( attributeCode == AjpConstants.SC_A_SSL_KEY_SIZE ) {
                // Bug 1326: it's an Integer.
                req.setAttribute(SSLSupport.KEY_SIZE_KEY,
                                 new Integer( msg.getInt()));
               //Integer.toString(msg.getInt()));
            }

            if( attributeCode == AjpConstants.SC_A_REQ_ATTRIBUTE ) {
                // 2 strings ???...
                msg.getBytes( tmpMB );
                String n=tmpMB.toString();
                msg.getBytes( tmpMB );
                String v=tmpMB.toString();
                /*
                 * AJP13 misses to forward the remotePort.
                 * Allow the AJP connector to add this info via
                 * a private request attribute.
                 * We will accept the forwarded data as the remote port,
                 * and remove it from the public list of request attributes.
                 */
                if(n.equals(AjpConstants.SC_A_REQ_REMOTE_PORT)) {
                    try {
                        req.setRemotePort(Integer.parseInt(v));
                    } catch (NumberFormatException nfe) {
                    }
                } else {
                    req.setAttribute(n, v );
                    if(log.isTraceEnabled())
                        log.trace("jk Attribute set " + n + "=" + v);
                }
            }


            // 1 string attributes
            switch(attributeCode) {
            case AjpConstants.SC_A_CONTEXT      :
                msg.getBytes( tmpMB );
                // nothing
                break;
                
            case AjpConstants.SC_A_SERVLET_PATH :
                msg.getBytes( tmpMB );
                // nothing 
                break;
                
            case AjpConstants.SC_A_REMOTE_USER  :
                if( tomcatAuthentication ) {
                    // ignore server
                    msg.getBytes( tmpMB );
                } else {
                    msg.getBytes(req.getRemoteUser());
                }
                break;
                
            case AjpConstants.SC_A_AUTH_TYPE    :
                if( tomcatAuthentication ) {
                    // ignore server
                    msg.getBytes( tmpMB );
                } else {
                    msg.getBytes(req.getAuthType());
                }
                break;
                
            case AjpConstants.SC_A_QUERY_STRING :
                msg.getBytes(req.queryString());
                break;
                
            case AjpConstants.SC_A_JVM_ROUTE    :
                msg.getBytes(req.instanceId());
                break;
                
            case AjpConstants.SC_A_SSL_CERT     :
                req.scheme().setString( "https" );
                // Transform the string into certificate.
                MessageBytes tmpMB2 = (MessageBytes)req.getNote(WorkerEnv.SSL_CERT_NOTE);
                if(tmpMB2 == null) {
                    tmpMB2 = MessageBytes.newInstance();
                    req.setNote(WorkerEnv.SSL_CERT_NOTE, tmpMB2);
                }
                // SSL certificate extraction is costy, moved to JkCoyoteHandler
                msg.getBytes(tmpMB2);
                break;
                
            case AjpConstants.SC_A_SSL_CIPHER   :
                req.scheme().setString( "https" );
                msg.getBytes(tmpMB);
                req.setAttribute(SSLSupport.CIPHER_SUITE_KEY,
                                 tmpMB.toString());
                break;
                
            case AjpConstants.SC_A_SSL_SESSION  :
                req.scheme().setString( "https" );
                msg.getBytes(tmpMB);
                req.setAttribute(SSLSupport.SESSION_ID_KEY, 
                                  tmpMB.toString());
                break;
                
            case AjpConstants.SC_A_SECRET  :
                msg.getBytes(tmpMB);
                String secret=tmpMB.toString();
                if(log.isTraceEnabled())
                    log.trace("Secret: " + secret );
                // endpoint note
                ep.setNote( secretNote, secret );
                break;
                
            case AjpConstants.SC_A_STORED_METHOD:
                msg.getBytes(req.method()); 
                break;
                
            default:
                break; // ignore, we don't know about it - backward compat
            }
        }
        return 200;
    }
    
    private void decodeHeaders( MsgContext ep, Msg msg, Request req,
                                MessageBytes tmpMB ) {
        // Decode headers
        MimeHeaders headers = req.getMimeHeaders();

        int hCount = msg.getInt();
        for(int i = 0 ; i < hCount ; i++) {
            String hName = null;

            // Header names are encoded as either an integer code starting
            // with 0xA0, or as a normal string (in which case the first
            // two bytes are the length).
            int isc = msg.peekInt();
            int hId = isc & 0xFF;

            MessageBytes vMB=null;
            isc &= 0xFF00;
            if(0xA000 == isc) {
                msg.getInt(); // To advance the read position
                hName = AjpConstants.headerTransArray[hId - 1];
                vMB=headers.addValue( hName );
            } else {
                // reset hId -- if the header currently being read
                // happens to be 7 or 8 bytes long, the code below
                // will think it's the content-type header or the
                // content-length header - SC_REQ_CONTENT_TYPE=7,
                // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
                // behaviour.  see bug 5861 for more information.
                hId = -1;
                msg.getBytes( tmpMB );
                ByteChunk bc=tmpMB.getByteChunk();
                vMB=headers.addValue( bc.getBuffer(),
                                      bc.getStart(), bc.getLength() );
            }

            msg.getBytes(vMB);

            if (hId == AjpConstants.SC_REQ_CONTENT_LENGTH ||
                (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
                // just read the content-length header, so set it
                long cl = vMB.getLong();
                if(cl < Integer.MAX_VALUE)
                    req.setContentLength( (int)cl );
            } else if (hId == AjpConstants.SC_REQ_CONTENT_TYPE ||
                (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
                // just read the content-type header, so set it
                ByteChunk bchunk = vMB.getByteChunk();
                req.contentType().setBytes(bchunk.getBytes(),
                                           bchunk.getOffset(),
                                           bchunk.getLength());
            }
        }
    }

    /**
     * Parse host.
     */
    private void parseHost(MessageBytes valueMB, Request request) 
        throws IOException {

        if (valueMB == null || valueMB.isNull()) {
            // HTTP/1.0
            // Default is what the socket tells us. Overriden if a host is 
            // found/parsed
            request.setServerPort(request.getLocalPort());
            request.serverName().duplicate(request.localName());
            return;
        }

        ByteChunk valueBC = valueMB.getByteChunk();
        byte[] valueB = valueBC.getBytes();
        int valueL = valueBC.getLength();
        int valueS = valueBC.getStart();
        int colonPos = -1;
        CharChunk hostNameC = (CharChunk)request.getNote(HOSTBUFFER);
        if(hostNameC == null) {
            hostNameC = new CharChunk(valueL);
            request.setNote(HOSTBUFFER, hostNameC);
        }
        hostNameC.recycle();

        boolean ipv6 = (valueB[valueS] == '[');
        boolean bracketClosed = false;
        for (int i = 0; i < valueL; i++) {
            char b = (char) valueB[i + valueS];
            hostNameC.append(b);
            if (b == ']') {
                bracketClosed = true;
            } else if (b == ':') {
                if (!ipv6 || bracketClosed) {
                    colonPos = i;
                    break;
                }
            }
        }

        if (colonPos < 0) {
            if (request.scheme().equalsIgnoreCase("https")) {
                // 80 - Default HTTTP port
                request.setServerPort(443);
            } else {
                // 443 - Default HTTPS port
                request.setServerPort(80);
            }
            request.serverName().setChars(hostNameC.getChars(), 
                                          hostNameC.getStart(), 
                                          hostNameC.getLength());
        } else {

            request.serverName().setChars(hostNameC.getChars(), 
                                          hostNameC.getStart(), colonPos);

            int port = 0;
            int mult = 1;
            for (int i = valueL - 1; i > colonPos; i--) {
                int charValue = HexUtils.getDec(valueB[i + valueS]);
                if (charValue == -1) {
                    // Invalid character
                    throw new CharConversionException("Invalid char in port: " + valueB[i + valueS]); 
                }
                port = port + (charValue * mult);
                mult = 10 * mult;
            }
            request.setServerPort(port);

        }

    }

}
