You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bi...@apache.org on 2002/05/24 06:38:59 UTC

cvs commit: jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi ByteArrayServletOutputStream.java ResponseIncludeWrapper.java SSIConfig.java SSIEcho.java SSIExec.java SSIExternalResolver.java SSIFlastmod.java SSIFsize.java SSIInclude.java SSIMediator.java SSIPrintenv.java SSIProcessor.java SSIServletExternalResolver.java SSIServletRequestUtil.java SSISet.java SSIStopProcessingException.java SSiCommand.java package.html

billbarker    02/05/23 21:38:59

  Added:       catalina/src/share/org/apache/catalina/ssi
                        ByteArrayServletOutputStream.java
                        ResponseIncludeWrapper.java SSIConfig.java
                        SSIEcho.java SSIExec.java SSIExternalResolver.java
                        SSIFlastmod.java SSIFsize.java SSIInclude.java
                        SSIMediator.java SSIPrintenv.java SSIProcessor.java
                        SSIServletExternalResolver.java
                        SSIServletRequestUtil.java SSISet.java
                        SSIStopProcessingException.java SSiCommand.java
                        package.html
  Log:
  New SsiServlet support classes.
  
  The new SSI support may not be perfect, but it is a much much better starting point for development than the old one.
  
  Submitted by: Dan Sandberg <x...@cs.stanford.edu>
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/ByteArrayServletOutputStream.java
  
  Index: ByteArrayServletOutputStream.java
  ===================================================================
  /*
   * ByteArrayServletOutputStream.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/ByteArrayServletOutputStream.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.OutputStream;
  import java.io.IOException;
  import java.io.ByteArrayOutputStream;
  import javax.servlet.ServletOutputStream;
  
  /**
   * Class that extends ServletOuputStream, used as a wrapper
   * from within <code>SsiInclude</code>
   *
   * @author Bip Thelin
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   * @see ServletOutputStream and ByteArrayOutputStream
   */
  public class ByteArrayServletOutputStream extends ServletOutputStream {
      /**
       * Our buffer to hold the stream
       */
      protected ByteArrayOutputStream _buf = null;
  
      /**
       * Construct a new ServletOutputStream
       *
       */
      public ByteArrayServletOutputStream() {
          _buf = new ByteArrayOutputStream();
      }
  
      /**
       * Write our stream to the <code>OutputStream</code> provided.
       *
       * @param out the OutputStream to write this stream to
       * @exception IOException if an input/output error occurs
       */
      public byte[] toByteArray() {
          return _buf.toByteArray();
      }
  
      /**
       * Write to our buffer
       *
       * @param b The parameter to write
       */
      public void write(int b) {
          _buf.write(b);
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/ResponseIncludeWrapper.java
  
  Index: ResponseIncludeWrapper.java
  ===================================================================
  /*
   * ResponseIncludeWrapper.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/ResponseIncludeWrapper.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.PrintWriter;
  import javax.servlet.ServletOutputStream;
  import javax.servlet.http.HttpServletResponse;
  import javax.servlet.http.HttpServletResponseWrapper;
  
  /**
   * A HttpServletResponseWrapper, used from <code>SSIServletExternalResolver</code>
   *
   * @author Bip Thelin
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public class ResponseIncludeWrapper extends HttpServletResponseWrapper {
  
      /**
       * Our ServletOutputStream
       */
      protected ServletOutputStream originalServletOutputStream;
      protected ServletOutputStream servletOutputStream;
      protected PrintWriter printWriter;
  
      /**
       * Initialize our wrapper with the current HttpServletResponse
       * and ServletOutputStream.
       *
       * @param res The HttpServletResponse to use
       * @param out The ServletOutputStream' to use
       */
      public ResponseIncludeWrapper(HttpServletResponse res,
                                    ServletOutputStream originalServletOutputStream) {
          super(res);
          this.originalServletOutputStream = originalServletOutputStream;
      }
  
      /**
       * Flush the servletOutputStream or printWriter ( only one will be non-null )
       *
       * This must be called after a requestDispatcher.include, since we can't assume that
       * the included servlet flushed its stream.
       */
      public void flushOutputStreamOrWriter() throws IOException {
  	if ( servletOutputStream != null ) {
  	    servletOutputStream.flush();
  	}
  	if ( printWriter != null ) {
  	    printWriter.flush();
  	}
      }
  
      /**
       * Return a printwriter, throws and exception if a
       * OutputStream already been returned.
       *
       * @return a PrintWriter object
       * @exception java.io.IOException if the outputstream already been called
       */
      public PrintWriter getWriter() throws java.io.IOException {
          if ( servletOutputStream == null ) {
  	    if ( printWriter == null ) {
  		printWriter = new PrintWriter( originalServletOutputStream );
  	    }
              return printWriter;
  	}
  	throw new IllegalStateException();
      }
  
      /**
       * Return a OutputStream, throws and exception if a
       * printwriter already been returned.
       *
       * @return a OutputStream object
       * @exception java.io.IOException if the printwriter already been called
       */
      public ServletOutputStream getOutputStream() throws java.io.IOException {
          if ( printWriter == null ) {
  	    if ( servletOutputStream == null ) {
  		servletOutputStream = originalServletOutputStream;
  	    }
  	    return servletOutputStream;
  	}
  	throw new IllegalStateException();
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIConfig.java
  
  Index: SSIConfig.java
  ===================================================================
  /*
   * SSIConfig.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIConfig.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.util.Properties;
  
  /**
   * Implements the Server-side #exec command
   *
   * @author Bip Thelin
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public final class SSIConfig implements SSICommand {
      /**
       * @see SSICommand
       */
      public void process(SSIMediator ssiMediator,
  			String[] paramNames, 
  			String[] paramValues,
  			PrintWriter writer ) {
  
          for(int i=0;i<paramNames.length;i++) {
  	    String paramName = paramNames[i];
  	    String paramValue = paramValues[i];
  
              if ( paramName.equalsIgnoreCase("errmsg") ) {
  		ssiMediator.setConfigErrMsg( paramValue );
              } else if ( paramName.equalsIgnoreCase("sizefmt") ) {
  		ssiMediator.setConfigSizeFmt( paramValue );
              } else if ( paramName.equalsIgnoreCase("timefmt") ) {
  		ssiMediator.setConfigTimeFmt( paramValue );
  	    } else {
  		ssiMediator.log("#config--Invalid attribute: " + paramName );
  		//We need to fetch this value each time, since it may change during the loop
  		String configErrMsg = ssiMediator.getConfigErrMsg();
  		writer.write( configErrMsg );
  	    }
          }
      }
  }
  
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIEcho.java
  
  Index: SSIEcho.java
  ===================================================================
  /*
   * SSIEcho.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIEcho.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  
  import java.io.PrintWriter;
  
  /**
   * Return the result associated with the supplied Server Variable.
   *
   * @author Bip Thelin
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public class SSIEcho implements SSICommand {
      protected final static String DEFAULT_ENCODING = "entity";
      protected final static String MISSING_VARIABLE_VALUE = "(none)";
  
      /**
       * @see SSICommand
       */
      public void process(SSIMediator ssiMediator,
  			String[] paramNames,
  			String[] paramValues,
  			PrintWriter writer) {
  
  	String encoding = DEFAULT_ENCODING;
  	String errorMessage = ssiMediator.getConfigErrMsg();
  
  	for ( int i=0; i < paramNames.length; i++ ) {
  	    String paramName = paramNames[i];
  	    String paramValue = paramValues[i];
  
  	    if ( paramName.equalsIgnoreCase("var") ) {
  		String variableValue = ssiMediator.getVariableValue( paramValue, encoding );
  		if ( variableValue == null ) {
  		    variableValue = MISSING_VARIABLE_VALUE;
  		}
  		writer.write( variableValue );
  	    } else if ( paramName.equalsIgnoreCase("encoding") ) {
  		if ( isValidEncoding( paramValue ) ) {
  		    encoding = paramValue;
  		} else {
  		    ssiMediator.log("#echo--Invalid encoding: " + paramValue );
  		    writer.write( errorMessage );
  		}
  	    } else {
  		ssiMediator.log("#echo--Invalid attribute: " + paramName );
  		writer.write( errorMessage );
  	    }
  	}
      }
  
      protected boolean isValidEncoding( String encoding ) {
  	return
  	    encoding.equalsIgnoreCase("url") ||
  	    encoding.equalsIgnoreCase("entity") ||
  	    encoding.equalsIgnoreCase("none");
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIExec.java
  
  Index: SSIExec.java
  ===================================================================
  /*
   * SSIExec.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIExec.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.BufferedInputStream;
  import java.io.BufferedOutputStream;
  import java.io.BufferedReader;
  import java.io.BufferedWriter;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  import java.io.Reader;
  import java.io.StringWriter;
  import java.io.Writer;
  import java.net.MalformedURLException;
  import java.net.URL;
  import javax.servlet.ServletException;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletOutputStream;
  import javax.servlet.RequestDispatcher;
  import org.apache.catalina.util.IOTools;
  
  /**
   * Implements the Server-side #exec command
   * 
   * @author Bip Thelin
   * @author Amy Roh
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   *
   */
  public class SSIExec implements SSICommand {   
      protected SSIInclude ssiInclude = new SSIInclude();
      protected final static int BUFFER_SIZE = 1024;
  
      /**
       * @see SSICommand
       */
      public void process(SSIMediator ssiMediator,
  			String[] paramNames,
  			String[] paramValues,
  			PrintWriter writer) {
  
  	String configErrMsg = ssiMediator.getConfigErrMsg();
  	String paramName = paramNames[0];
  	String paramValue = paramValues[0];
  
          if ( paramName.equalsIgnoreCase("cgi") ) {
  	    ssiInclude.process( ssiMediator, new String[] {"virtual"}, new String[] {paramValue}, writer );
          } else if ( paramName.equalsIgnoreCase("cmd") ) {
  	    boolean foundProgram = false;
  	    try {
  		Runtime rt = Runtime.getRuntime();
  		Process proc = rt.exec( paramValue );
  		foundProgram = true;
  
  		BufferedReader stdOutReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
  		BufferedReader stdErrReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
  
  		char[] buf = new char[BUFFER_SIZE];
  		IOTools.flow( stdErrReader, writer, buf );
  		IOTools.flow( stdOutReader, writer, buf );
  		proc.waitFor();
  	    } catch ( InterruptedException e ) {
  		ssiMediator.log( "Couldn't exec file: " + paramValue, e );
  		writer.write( configErrMsg );
  	    } catch ( IOException e ) {
  		if ( !foundProgram ) {
  		    //apache doesn't output an error message if it can't find a program
  		}
  		ssiMediator.log( "Couldn't exec file: " + paramValue, e );
  	    }
  	} 
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIExternalResolver.java
  
  Index: SSIExternalResolver.java
  ===================================================================
  /*
   * SSIExternalResolver.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIExternalResolver.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.util.Collection;
  import java.util.Date;
  
  /**
   * Interface used by SSIMediator to talk to the 'outside world' ( usually a servlet )
   * 
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   *
   */
  public interface SSIExternalResolver {
      /**
       * Adds any external variables to the variableNames collection.
       *
       * @param variableNames the collection to add to
       */
      public void addVariableNames( Collection variableNames );
  
      public String getVariableValue( String name );
  
      /**
       * Set the named variable to the specified value.
       *
       * If value is null, then the variable will be removed ( ie.
       * a call to getVariableValue will return null )
       *
       * @param name of the variable
       * @param value of the variable
       */
      public void setVariableValue( String name, String value );
  
  
      /**
       * Returns the current date.
       *
       * This is useful for putting the SSI stuff in a regression test.  Since you can make the current date a 
       * constant, it makes testing easier since the output won't change.
       *
       * @return the data
       */
      public Date getCurrentDate();
      public long getFileSize( String path, boolean virtual ) throws IOException;
      public long getFileLastModified( String path, boolean virtual ) throws IOException;
      public String getFileText( String path, boolean virtual ) throws IOException;
      public void log( String message, Throwable throwable );
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIFlastmod.java
  
  Index: SSIFlastmod.java
  ===================================================================
  /*
   * SSIFlastmod.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIFlastmod.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import org.apache.catalina.util.DateTool;
  import org.apache.catalina.util.Strftime;
  
  /**
   * Implements the Server-side #flastmod command
   *
   * @author Bip Thelin
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public final class SSIFlastmod implements SSICommand {
      /**
       * @see SSICommand
       */
      public void process(SSIMediator ssiMediator,
  			String[] paramNames,
  			String[] paramValues,
  			PrintWriter writer) {
  
  	String configErrMsg = ssiMediator.getConfigErrMsg();
  	StringBuffer buf = new StringBuffer();
  
          for(int i=0;i<paramNames.length;i++) {
  	    String paramName = paramNames[i];
  	    String paramValue = paramValues[i];
  
  	    try {
  		if ( paramName.equalsIgnoreCase("file") ||
  		     paramName.equalsIgnoreCase("virtual") ) {
  		    boolean virtual = paramName.equalsIgnoreCase("virtual");
  		    long lastModified = ssiMediator.getFileLastModified( paramValue,  virtual );
  		    Date date = new Date( lastModified );
  		    String configTimeFmt = ssiMediator.getConfigTimeFmt();
  		    writer.write( formatDate(date, configTimeFmt ) );
  		} else {
  		    ssiMediator.log("#flastmod--Invalid attribute: " + paramName );
  		    writer.write( configErrMsg );
  		}	    
  	    } catch ( IOException e ) {
  		ssiMediator.log("#flastmod--Couldn't get last modified for file: " + paramValue, e );
  		writer.write( configErrMsg );
  	    }
  	}
      }
  
      protected String formatDate( Date date, String configTimeFmt ) {
  	Strftime strftime = new Strftime( configTimeFmt, DateTool.LOCALE_US );
  	return strftime.format( date );
      }
  }
  
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIFsize.java
  
  Index: SSIFsize.java
  ===================================================================
  /*
   * SSIFsize.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIFsize.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.text.DecimalFormat;
  
  /**
   * Implements the Server-side #fsize command
   *
   * @author Bip Thelin
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public final class SSIFsize implements SSICommand {
      protected final static int ONE_KILOBYTE = 1024;
      protected final static int ONE_MEGABYTE = 1024 * 1024;
  
      /**
       * @see SSICommand
       */
      public void process(SSIMediator ssiMediator,
  			  String[] paramNames,
  			  String[] paramValues,
  			  PrintWriter writer) {
  
  	String configErrMsg = ssiMediator.getConfigErrMsg();
          for(int i=0;i<paramNames.length;i++) {
  	    String paramName = paramNames[i];
  	    String paramValue = paramValues[i];
  
  	    try {
  		if ( paramName.equalsIgnoreCase("file") ||
  		     paramName.equalsIgnoreCase("virtual") ) {
  		    boolean virtual = paramName.equalsIgnoreCase("virtual");
  		    long size = ssiMediator.getFileSize( paramValue,  virtual );
  		    String configSizeFmt = ssiMediator.getConfigSizeFmt();
  		    writer.write( formatSize(size, configSizeFmt ) );
  		} else {
  		    ssiMediator.log("#fsize--Invalid attribute: " + paramName );
  		    writer.write( configErrMsg );
  		}
  	    } catch ( IOException e ) {
  		ssiMediator.log("#fsize--Couldn't get size for file: " + paramValue, e );
  		writer.write( configErrMsg );
  	    }
  	}
      }
  
      //We try to mimick Apache here, as we do everywhere
      protected String formatSize(long size, String format) {
          String retString = "";
  
          if ( format.equalsIgnoreCase("bytes") ) {
  	    DecimalFormat decimalFormat = new DecimalFormat("#,##0");
  	    retString = decimalFormat.format( size );
          } else {
  	    if ( size == 0 ) {
  		retString = " 0k";
              } else if ( size < ONE_KILOBYTE ) {
  		retString = " 1k";
  	    } else if ( size < ONE_MEGABYTE ) {
  		DecimalFormat decimalFormat = new DecimalFormat(" 0k");
  		retString = decimalFormat.format( size  / (double) ONE_KILOBYTE );
              } else {
  		DecimalFormat decimalFormat = new DecimalFormat(" #,##0.0M");
  		retString = decimalFormat.format( size  / (double) ONE_MEGABYTE );
  	    }
          }
  
          return retString;
      }
  }
  
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIInclude.java
  
  Index: SSIInclude.java
  ===================================================================
  /*
   * SSIInclude.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIInclude.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  import javax.servlet.ServletException;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletOutputStream;
  import javax.servlet.RequestDispatcher;
  
  /**
   * Implements the Server-side #include command
   *
   * @author Bip Thelin
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public final class SSIInclude implements SSICommand {
      /**
       * @see SSICommand
       */
      public void process(SSIMediator ssiMediator,
  			String[] paramNames,
  			String[] paramValues,
  			PrintWriter writer) {
  
  	String configErrMsg = ssiMediator.getConfigErrMsg();
  
  	for ( int i=0; i < paramNames.length; i++ ) {
  	    String paramName = paramNames[i];
  	    String paramValue = paramValues[i];
  
  	    try {
  		if ( paramName.equalsIgnoreCase("file") ||
  		     paramName.equalsIgnoreCase("virtual") ) {
  		    boolean virtual = paramName.equalsIgnoreCase("virtual");
  		    String text = ssiMediator.getFileText( paramValue, virtual );
  		    writer.write( text );
  		} else {
  		    ssiMediator.log("#include--Invalid attribute: " + paramName );
  		    writer.write( configErrMsg );
  		}
  	    } catch ( IOException e ) {
  		ssiMediator.log("#include--Couldn't include file: " + paramValue, e );
  		writer.write( configErrMsg );
  	    }
  	}
      }
  }
  
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIMediator.java
  
  Index: SSIMediator.java
  ===================================================================
  /*
   * SSIMediator.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIMediator.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.io.StringWriter;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Set;
  import java.util.TimeZone;
  import org.apache.catalina.util.DateTool;
  import org.apache.catalina.util.URLEncoder;
  import org.apache.catalina.util.Strftime;
  
  /**
   * Allows the different SSICommand implementations to share data/talk to each other
   *
   * @author Bip Thelin
   * @author Amy Roh
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public class SSIMediator {
      protected final static String DEFAULT_CONFIG_ERR_MSG = "[an error occurred while processing this directive]";
      protected final static String DEFAULT_CONFIG_TIME_FMT = "%A, %d-%b-%Y %T %Z";
      protected final static String DEFAULT_CONFIG_SIZE_FMT = "abbrev";
      protected static URLEncoder urlEncoder;
      protected String configErrMsg = DEFAULT_CONFIG_ERR_MSG;
      protected String configTimeFmt = DEFAULT_CONFIG_TIME_FMT;
      protected String configSizeFmt = DEFAULT_CONFIG_SIZE_FMT;
      protected String className = getClass().getName();
      protected SSIExternalResolver ssiExternalResolver;
      protected Date lastModifiedDate;
      protected int debug;
      protected Strftime strftime;
  
      static {
  	//We try to encode only the same characters that apache does
  	urlEncoder = new URLEncoder();
  	urlEncoder.addSafeCharacter(',');
  	urlEncoder.addSafeCharacter(':');
  	urlEncoder.addSafeCharacter('-');
          urlEncoder.addSafeCharacter('_');
          urlEncoder.addSafeCharacter('.');
          urlEncoder.addSafeCharacter('*');
          urlEncoder.addSafeCharacter('/');
          urlEncoder.addSafeCharacter('!');
          urlEncoder.addSafeCharacter('~');
          urlEncoder.addSafeCharacter('\'');
          urlEncoder.addSafeCharacter('(');
          urlEncoder.addSafeCharacter(')');
      }
  
      public SSIMediator( SSIExternalResolver ssiExternalResolver, 
  			Date lastModifiedDate,
  			int debug ) {
  	this.ssiExternalResolver = ssiExternalResolver;	
  	this.lastModifiedDate = lastModifiedDate;
  	this.debug = debug;
  
  	setConfigTimeFmt( DEFAULT_CONFIG_TIME_FMT, true );
      }
      
      public void setConfigErrMsg( String configErrMsg ) {
  	this.configErrMsg = configErrMsg;
      }
  
      public void setConfigTimeFmt( String configTimeFmt ) {
  	setConfigTimeFmt( configTimeFmt, false );
      }
  
      public void setConfigTimeFmt( String configTimeFmt, boolean fromConstructor ) {
  	this.configTimeFmt = configTimeFmt;
  
  	//What's the story here with DateTool.LOCALE_US?? Why??
  	this.strftime = new Strftime( configTimeFmt, DateTool.LOCALE_US );
  
  	//Variables like DATE_LOCAL, DATE_GMT, and LAST_MODIFIED need to be updated when
  	//the timefmt changes.  This is what Apache SSI does.
  	setDateVariables( fromConstructor );
      }
  
      public void setConfigSizeFmt( String configSizeFmt ) {
  	this.configSizeFmt = configSizeFmt;
      }
  
      public String getConfigErrMsg() {
  	return configErrMsg;
      }
  
      public String getConfigTimeFmt() {
  	return configTimeFmt;
      }
  
      public String getConfigSizeFmt() {
  	return configSizeFmt;
      }
  
      public Collection getVariableNames() {
  	Set variableNames = new HashSet();
  	//These built-in variables are supplied by the mediator ( if not over-written by the user ) and always exist
  	variableNames.add( "DATE_GMT" );
  	variableNames.add( "DATE_LOCAL" );
  	variableNames.add( "LAST_MODIFIED" );
  	ssiExternalResolver.addVariableNames( variableNames );
  
  	//Remove any variables that are reserved by this class
  	Iterator iter = variableNames.iterator();
  	while ( iter.hasNext() ) {
  	    String name = (String) iter.next();
  	    if ( isNameReserved( name ) ) {
  		iter.remove();
  	    }
  	}
  	return variableNames;	   
      }
  
      public long getFileSize( String path, boolean virtual ) throws IOException {
  	return ssiExternalResolver.getFileSize( path, virtual );
      }
  
      public long getFileLastModified( String path, boolean virtual ) throws IOException {
  	return ssiExternalResolver.getFileLastModified( path, virtual );
      }
      
      public String getFileText( String path, boolean virtual ) throws IOException {
  	return ssiExternalResolver.getFileText( path, virtual );
      }
  
      protected boolean isNameReserved( String name ) {
  	return name.startsWith( className + "." );
      }
  
      public String getVariableValue( String variableName ) {
  	return getVariableValue( variableName, "none" );
      }
  
      public void setVariableValue( String variableName, String variableValue ) {
  	if ( !isNameReserved( variableName ) ) {
  	    ssiExternalResolver.setVariableValue( variableName, variableValue );
  	}
      }
  
      public String getVariableValue( String variableName, String encoding ) {
  	String lowerCaseVariableName = variableName.toLowerCase();
  	String variableValue = null;
  
  	if ( !isNameReserved( lowerCaseVariableName ) ) {
  	    //Try getting it externally first, if it fails, try getting the 'built-in' value
  	    variableValue = ssiExternalResolver.getVariableValue( variableName );
  	    if ( variableValue == null ) {
  		variableName = variableName.toUpperCase();
  		variableValue = (String) ssiExternalResolver.getVariableValue( className + "." + variableName );
  	    }
  	    if ( variableValue != null ) {
  		variableValue = encode( variableValue, encoding );
  	    }
  	}
  	return variableValue;
      }
  
      protected String formatDate( Date date, TimeZone timeZone ) {
  	String retVal;
  
  	if ( timeZone != null ) {
  	    //we temporarily change strftime.  Since SSIMediator is inherently single-threaded, this
  	    //isn't a problem
  	    TimeZone oldTimeZone = strftime.getTimeZone();
  	    strftime.setTimeZone( timeZone );
  	    retVal = strftime.format(date);    
  	    strftime.setTimeZone( oldTimeZone );
  	} else {
  	    retVal = strftime.format(date);    
  	}
  	return retVal;
      }
  
      protected String encode( String value, String encoding ) {
  	String retVal = null;
  
  	if ( encoding.equalsIgnoreCase( "url" ) ) {
  	    retVal = urlEncoder.encode( value );
  	} else if ( encoding.equalsIgnoreCase( "none" ) ) {
  	    retVal = value;
  	} else if ( encoding.equalsIgnoreCase( "entity" ) ) {
  	    //Not sure how this is really different than none
  	    retVal = value;
  	} else {
  	    //This shouldn't be possible
  	    throw new IllegalArgumentException("Unknown encoding: " + encoding);
  	}
   	return retVal;
      }
  
      public void log( String message ) {
  	ssiExternalResolver.log( message, null );
      }
  
      public void log( String message, Throwable throwable ) {
  	ssiExternalResolver.log( message, throwable );
      }
  
      protected void setDateVariables( boolean fromConstructor ) {
  	boolean alreadySet = ssiExternalResolver.getVariableValue( className + ".alreadyset" ) != null;
  	//skip this if we are being called from the constructor, and this has already been set
  	if ( !( fromConstructor && alreadySet ) ) {
  	    ssiExternalResolver.setVariableValue( className + ".alreadyset", "true" );
  
  	    Date date = new Date();
  	    TimeZone timeZone = TimeZone.getTimeZone("GMT");
  	    String retVal =  formatDate( date, timeZone );
  	    
  	    //If we are setting on of the date variables, we want to remove them from the user
  	    //defined list of variables, because this is what Apache does
  	    setVariableValue ( "DATE_GMT", null ); 
  	    ssiExternalResolver.setVariableValue ( className + ".DATE_GMT", retVal ); 
  	    
  	    retVal = formatDate( date, null );
  	    setVariableValue ( "DATE_LOCAL", null );
  	    ssiExternalResolver.setVariableValue ( className + ".DATE_LOCAL", retVal );
  	    
  	    retVal = formatDate( lastModifiedDate, null );
  	    setVariableValue ( "LAST_MODIFIED", null );
  	    ssiExternalResolver.setVariableValue ( className + ".LAST_MODIFIED", retVal );
  	}
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIPrintenv.java
  
  Index: SSIPrintenv.java
  ===================================================================
  /*
   * SSIPrintenv.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIPrintenv.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.PrintWriter;
  import java.util.Collection;
  import java.util.Iterator;
  
  /**
   * Implements the Server-side #printenv command
   *
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public class SSIPrintenv implements SSICommand {
      /**
       * @see SSICommand
       */
      public void process(SSIMediator ssiMediator,
  			String[] paramNames,
  			String[] paramValues,
  			PrintWriter writer) {
  
  	//any arguments should produce an error
  	if ( paramNames.length > 0 ) {
  	    String errorMessage = ssiMediator.getConfigErrMsg();
  	    writer.write( errorMessage );
  	} else {
  	    Collection variableNames = ssiMediator.getVariableNames();
  	    Iterator iter = variableNames.iterator();
  	    while ( iter.hasNext() ) {
  		String variableName = (String) iter.next();
  		String variableValue = ssiMediator.getVariableValue( variableName );
  		//This shouldn't happen, since all the variable names must have values
  		if ( variableValue == null ) {
  		    variableValue = "(none)";
  		}
  		writer.write( variableName );
  		writer.write( '=' );
  		writer.write( variableValue );
  		writer.write( '\n' );
  	    }
  	}
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIProcessor.java
  
  Index: SSIProcessor.java
  ===================================================================
  /*
   * SSIProcessor.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIProcessor.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.io.Reader;
  import java.io.StringWriter;
  import java.io.Writer;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.StringTokenizer;
  import org.apache.catalina.util.IOTools;
  
  /**
   * The entry point to SSI processing.  This class does the actual parsing, delegating to the SSIMediator, SSICommand, and
   * SSIExternalResolver as necessary[
   * 
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   *
   */
  public class SSIProcessor {
      /** The start pattern */
      protected final static String COMMAND_START = "<!--#";
  
      /** The end pattern */
      protected final static String COMMAND_END = "-->";
      protected final static int BUFFER_SIZE = 4096;
  
      protected SSIExternalResolver ssiExternalResolver;
      protected HashMap commands = new HashMap();
      protected int debug;
      
      public SSIProcessor( SSIExternalResolver ssiExternalResolver, int debug ) {
  	this.ssiExternalResolver = ssiExternalResolver;
  	this.debug = debug;
  	addBuiltinCommands();
      }
  
      protected void addBuiltinCommands() {
  	addCommand( "config", new SSIConfig() );
  	addCommand( "echo", new SSIEcho() );
  	addCommand( "exec", new SSIExec() );
  	addCommand( "include", new SSIInclude() );
  	addCommand( "flastmod", new SSIFlastmod() );
  	addCommand( "fsize", new SSIFsize() );
  	addCommand( "printenv", new SSIPrintenv() );
  	addCommand( "set", new SSISet() );
      }
  
      public void addCommand( String name, SSICommand command ) {
  	commands.put( name, command );
      }
  
      /**
       * Process a file with server-side commands, reading from reader and writing the processed
       * version to writer.
       *
       * NOTE: We really should be doing this in a streaming way rather than converting it to an array first.
       *
       * @param reader the reader to read the file containing SSIs from
       * @param writer the writer to write the file with the SSIs processed.
       * @throws IOException when things go horribly awry. Should be unlikely since
       *                     the SSICommand usually catches 'normal' IOExceptions.
       */
      public void process( Reader reader, Date lastModifiedDate, PrintWriter writer ) throws IOException {
  	SSIMediator ssiMediator = new SSIMediator( ssiExternalResolver, 
  						   lastModifiedDate,
  						   debug );
  
  	StringWriter stringWriter = new StringWriter();
  	IOTools.flow( reader, stringWriter );
  	String fileContents = stringWriter.toString();
  	stringWriter = null;
  
          int index = 0;
  	boolean inside = false;
          StringBuffer command = new StringBuffer();
  	try {
  	    while (index < fileContents.length()) {
  		char c = fileContents.charAt( index );
  		if ( !inside ) {
  		    if ( c == COMMAND_START.charAt( 0 ) && charCmp( fileContents, index, COMMAND_START ) ) {
  			inside = true;
  			index += COMMAND_START.length();
  			command.setLength( 0 ); //clear the command string
  		    } else {
  			writer.write( c );
  			index++;
  		    }
  		} else {
  		    if ( c == COMMAND_END.charAt( 0 ) && charCmp( fileContents, index, COMMAND_END ) ) {
  			inside = false;
  			index += COMMAND_END.length();
  			String strCmd = parseCmd(command);
  			if ( debug > 0 ) {
  			    ssiExternalResolver.log( "SSIProcessor.process -- processing command: " + strCmd, null );
  			}
  			String[] paramNames = parseParamNames(command, strCmd.length());
  			String[] paramValues = parseParamValues(command, strCmd.length());
  			
  			//We need to fetch this value each time, since it may change during the loop
  			String configErrMsg = ssiMediator.getConfigErrMsg();		    
  			SSICommand ssiCommand = (SSICommand) commands.get(strCmd.toLowerCase());
  			if ( ssiCommand != null ) {
  			    if ( paramNames.length==paramValues.length ) {			    
  				ssiCommand.process( ssiMediator, paramNames, paramValues, writer );
  			    } else {
  				ssiExternalResolver.log( "Parameter names count does not match parameter values count on command: " + strCmd, null );
  				writer.write( configErrMsg );
  			    }
  			} else {
  			    ssiExternalResolver.log( "Unknown command: " + strCmd, null);
  			    writer.write( configErrMsg );
  			}
  		    } else {
  			command.append( c );
  			index++;		   		    		    
  		    }
  		}
  	    }
  	} catch ( SSIStopProcessingException e ) {
  	    //If we are here, then we have already stopped processing, so all is good
  	}	
      }
  
      /**
       * Parse a StringBuffer and take out the param type token.
       * Called from <code>requestHandler</code>
       * @param cmd a value of type 'StringBuffer'
       * @return a value of type 'String[]'
       */
      protected String[] parseParamNames(StringBuffer cmd, int start) {
          int bIdx = start;
          int i = 0;
          int quotes = 0;
          boolean inside = false;
          StringBuffer retBuf = new StringBuffer();
  
          while(bIdx < cmd.length()) {
              if(!inside) {
                  while(bIdx < cmd.length()&&isSpace(cmd.charAt(bIdx)))
                      bIdx++;
  
                  if(bIdx>=cmd.length())
                      break;
  
                  inside=!inside;
              } else {
                  while(bIdx < cmd.length()&&cmd.charAt(bIdx)!='=') {
                      retBuf.append(cmd.charAt(bIdx));
                      bIdx++;
                  }
  
                  retBuf.append('"');
                  inside=!inside;
                  quotes=0;
  
                  while(bIdx < cmd.length()&&quotes!=2) {
                      if(cmd.charAt(bIdx)=='"')
                              quotes++;
  
                      bIdx++;
                  }
              }
          }
  
          StringTokenizer str = new StringTokenizer(retBuf.toString(), "\"");
          String[] retString = new String[str.countTokens()];
  
          while(str.hasMoreTokens()) {
              retString[i++] = str.nextToken().trim();
          }
  
          return retString;
      }
  
      /**
       * Parse a StringBuffer and take out the param token.
       * Called from <code>requestHandler</code>
       * @param cmd a value of type 'StringBuffer'
       * @return a value of type 'String[]'
       */
      protected String[] parseParamValues(StringBuffer cmd, int start) {
          int bIdx = start;
          int i = 0;
          int quotes = 0;
          boolean inside = false;
          StringBuffer retBuf = new StringBuffer();
  
          while(bIdx < cmd.length()) {
              if(!inside) {
                  while(bIdx < cmd.length()&&
                        cmd.charAt(bIdx)!='"')
                      bIdx++;
  
                  if(bIdx>=cmd.length())
                      break;
  
                  inside=!inside;
              } else {
                  while(bIdx < cmd.length() && cmd.charAt(bIdx)!='"') {
                      retBuf.append(cmd.charAt(bIdx));
                      bIdx++;
                  }
  
                  retBuf.append('"');
                  inside=!inside;
              }
  
              bIdx++;
          }
  
          StringTokenizer str = new StringTokenizer(retBuf.toString(), "\"");
          String[] retString = new String[str.countTokens()];
  
          while(str.hasMoreTokens()) {
              retString[i++] = str.nextToken();
          }
  
          return retString;
      }
  
      /**
       * Parse a StringBuffer and take out the command token.
       * Called from <code>requestHandler</code>
       * @param cmd a value of type 'StringBuffer'
       * @return a value of type 'String', or null if there is none
       */
      private String parseCmd(StringBuffer cmd) {
  	int firstLetter = -1;
  	int lastLetter = -1;
  	for ( int i=0; i < cmd.length(); i++ ) {
  	    char c = cmd.charAt( i );
  	    if ( Character.isLetter( c ) ) {
  		if ( firstLetter == -1 ) {
  		    firstLetter = i;
  		}
  		lastLetter = i;
  	    } else if ( isSpace( c ) ) {
  		if ( lastLetter > -1 ) {
  		    break;
  		}
  	    } else {
  		break;
  	    }
  	}
  
  	String command = null;
  	if ( firstLetter != -1 ) {
  	    command = cmd.substring( firstLetter, lastLetter + 1 );
  	}
          return command;
      }
  
      protected boolean charCmp(String buf, int index, String command) {
  	return buf.regionMatches( index, command, 0, command.length() );
      }
  
      protected boolean isSpace(char c) {
          return c==' '||c=='\n'||c=='\t'||c=='\r';
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIServletExternalResolver.java
  
  Index: SSIServletExternalResolver.java
  ===================================================================
  /*
   * SSIServletExternalResolver.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIServletExternalResolver.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  import java.io.BufferedInputStream;
  import java.io.BufferedReader;
  import java.io.ByteArrayOutputStream;
  import java.io.PrintWriter;
  import java.io.Reader;
  import java.io.StringWriter;
  import java.io.Writer;
  import java.net.URL;
  import java.net.URLConnection;
  import java.net.URLDecoder;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Date;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.Locale;
  import java.text.SimpleDateFormat;
  import java.util.StringTokenizer;
  import java.util.TimeZone;
  import javax.servlet.RequestDispatcher;
  import javax.servlet.ServletException;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletOutputStream;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import org.apache.catalina.Globals;
  import org.apache.catalina.util.RequestUtil;
  
  /**
   * An implementation of SSIExternalResolver that is used with servlets.
   *
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public class SSIServletExternalResolver implements SSIExternalResolver {
      protected final String VARIABLE_NAMES[] = {
  	"AUTH_TYPE","CONTENT_LENGTH","CONTENT_TYPE","DOCUMENT_NAME",
  	"DOCUMENT_URI","GATEWAY_INTERFACE","PATH_INFO", "PATH_TRANSLATED",
  	"QUERY_STRING","QUERY_STRING_UNESCAPED","REMOTE_ADDR","REMOTE_HOST",
  	"REMOTE_USER","REQUEST_METHOD","SCRIPT_NAME","SERVER_NAME","SERVER_PORT",
  	"SERVER_PROTOCOL","SERVER_SOFTWARE" };
      
      protected HttpServlet servlet;
      protected HttpServletRequest req;
      protected HttpServletResponse res;
      protected boolean isVirtualWebappRelative;
      protected int debug;
  
      public SSIServletExternalResolver( HttpServlet servlet, HttpServletRequest req, HttpServletResponse res, 
  				       boolean isVirtualWebappRelative,
  				       int debug ) {
  	this.servlet = servlet;
  	this.req = req;
  	this.res = res;
  	this.isVirtualWebappRelative = isVirtualWebappRelative;
  	this.debug = debug;
      }
  
      public void log( String message, Throwable throwable ) {
  	//We can't assume that Servlet.log( message, null )
  	//is the same as Servlet.log( message ), since API
  	//doesn't seem to say so.
  	if ( throwable != null ) {
  	    servlet.log( message, throwable );
  	} else {
  	    servlet.log( message );
  	}
      }
  
      public void addVariableNames( Collection variableNames ) {
  	for ( int i=0; i < VARIABLE_NAMES.length; i++ ) {
  	    String variableName = VARIABLE_NAMES[ i ];
  	    String variableValue = getVariableValue( variableName );
  	    if ( variableValue != null ) {
  		variableNames.add( variableName );
  	    }
  	}
  	Enumeration e = req.getAttributeNames();
  	while ( e.hasMoreElements() ) {
  	    String name = (String) e.nextElement();
  	    if ( !isNameReserved( name ) ) {
  		variableNames.add( name );
  	    }
  	}
      }
  
      protected Object getReqAttributeIgnoreCase( String targetName ) {
  	Object object = null;
  	    
  	if ( !isNameReserved( targetName ) ) {
  	    object = req.getAttribute( targetName );
  	    if ( object == null ) {
  		Enumeration e = req.getAttributeNames();
  		while ( e.hasMoreElements() ) {
  		    String name = (String) e.nextElement();
  		    if ( targetName.equalsIgnoreCase( name ) &&
  			 !isNameReserved( name ) ) {
  
  			object = req.getAttribute( name );
  			if ( object != null ) {
  			    break;
  			}
  		    }
  		}
  	    }
  	}
  	return object;
      }
  
      protected boolean isNameReserved( String name ) {
  	return 
  	    name.startsWith("java.") ||
  	    name.startsWith("javax.") ||
  	    name.startsWith("sun.");
      }
  
      public void setVariableValue( String name, String value ) {
  	if ( !isNameReserved( name ) ) {
  	    req.setAttribute( name, value );
  	}
      }
  
      public String getVariableValue( String name ) {
  	String retVal = null;
  
  	Object object = getReqAttributeIgnoreCase( name );
  	if ( object != null ) {
  	    retVal = object.toString();
  	} else {
  	    retVal = getCGIVariable( name );
  	}
  	return retVal;
      }
  
      protected String getCGIVariable( String name ) {
  	String retVal = null;
  
  	if ( name.equalsIgnoreCase( "AUTH_TYPE" ) ) {
  	    retVal = req.getAuthType();
  	} else if ( name.equalsIgnoreCase( "CONTENT_LENGTH" ) ) {
  	    int contentLength = req.getContentLength();
  	    if ( contentLength >= 0 ) {
  		retVal = Integer.toString( contentLength );
  	    }
  	} else if ( name.equalsIgnoreCase( "CONTENT_TYPE" ) ) {
  	    retVal = req.getContentType();
  	} else if ( name.equalsIgnoreCase( "DOCUMENT_NAME" ) ) {
  	    String requestURI = req.getRequestURI();
  	    retVal = requestURI.substring( requestURI.lastIndexOf('/') + 1 );
  	} else if ( name.equalsIgnoreCase( "DOCUMENT_URI" ) ) {
  	    retVal = req.getRequestURI();
  	} else if ( name.equalsIgnoreCase( "GATEWAY_INTERFACE" ) ) {
  	    retVal = "CGI/1.1";
  	} else if ( name.equalsIgnoreCase( "PATH_INFO" ) ) {
  	    retVal = req.getPathInfo();
  	} else if ( name.equalsIgnoreCase( "PATH_TRANSLATED" ) ) {
  	    retVal = req.getPathTranslated();
  	} else if ( name.equalsIgnoreCase( "QUERY_STRING" ) ) {
  	    //apache displays this as an empty string rather than (none)
  	    retVal = nullToEmptyString( req.getQueryString() );
  	} else if ( name.equalsIgnoreCase( "QUERY_STRING_UNESCAPED" ) ) {
  	    String queryString = req.getQueryString();
  	    if ( queryString != null ) {
  		retVal = URLDecoder.decode( queryString );
  	    }
  	} else if ( name.equalsIgnoreCase( "REMOTE_ADDR" ) ) {
  	    retVal = req.getRemoteAddr();
  	} else if ( name.equalsIgnoreCase( "REMOTE_HOST" ) ) {
  	    retVal = req.getRemoteHost();	   
  	} else if ( name.equalsIgnoreCase( "REMOTE_USER" ) ) {
  	    retVal = req.getRemoteUser();
  	} else if ( name.equalsIgnoreCase( "REQUEST_METHOD" ) ) {
  	    retVal = req.getMethod();
  	} else if ( name.equalsIgnoreCase( "SCRIPT_NAME" ) ) {
  	    retVal = req.getServletPath();
  	} else if ( name.equalsIgnoreCase( "SERVER_NAME" ) ) {
  	    retVal = req.getServerName();
  	} else if ( name.equalsIgnoreCase( "SERVER_PORT" ) ) {
  	    retVal = Integer.toString( req.getServerPort() );
  	} else if ( name.equalsIgnoreCase( "SERVER_PROTOCOL" ) ) {
  	    retVal = req.getProtocol();
  	} else if ( name.equalsIgnoreCase( "SERVER_SOFTWARE" ) ) {
  	    ServletContext servletContext = servlet.getServletContext();	   
  	    retVal = servletContext.getServerInfo();
  	}
  	return retVal;
      }
  
      public Date getCurrentDate() {
  	return new Date();
      }       
  
      protected String nullToEmptyString( String string ) {
  	String retVal = string;
  
  	if ( retVal == null ) {
  	    retVal="";
  	}
  	return retVal;
      }
  
  
      protected String getPathWithoutFileName( String servletPath ) {
  	String retVal = null;
  
  	int lastSlash = servletPath.lastIndexOf('/');
  	if ( lastSlash >= 0 ) {
  	    //cut off file namee
  	    retVal = servletPath.substring( 0, lastSlash + 1 );
  	}
  	return retVal;
      }
  
      protected String getPathWithoutContext( String servletPath ) {
  	String retVal = null;
  
  	int secondSlash = servletPath.indexOf('/', 1 );
  	if ( secondSlash >= 0 ) {
  	    //cut off context
  	    retVal = servletPath.substring( secondSlash );
  	}
  	return retVal;
      }
  
      protected String getAbsolutePath( String path ) throws IOException {
  	String pathWithoutContext = SSIServletRequestUtil.getRelativePath( req );
  	String prefix = getPathWithoutFileName( pathWithoutContext );
  	if ( prefix == null ) {
  	    throw new IOException("Couldn't remove filename from path: " + pathWithoutContext );
  	}
  	String fullPath = prefix + path;
  	String retVal = SSIServletRequestUtil.normalize( fullPath );
  
  	if ( retVal == null ) {
  	    throw new IOException("Normalization yielded null on path: " + fullPath );
  	}
  	return retVal;
      }
  
      protected ServletContextAndPath getServletContextAndPathFromNonVirtualPath( String nonVirtualPath ) throws IOException {
  	if ( nonVirtualPath.startsWith("/") || nonVirtualPath.startsWith("\\") ) {
  	    throw new IOException("A non-virtual path can't be absolute: " + nonVirtualPath );
  	} 
  
  	if ( nonVirtualPath.indexOf("../") >= 0 ) {
  	    throw new IOException("A non-virtual path can't contain '../' : " + nonVirtualPath );
  	}
  
  	String path = getAbsolutePath( nonVirtualPath );
  
  	ServletContext servletContext = servlet.getServletContext();
  	ServletContextAndPath csAndP = new ServletContextAndPath( servletContext, path );
  	return csAndP;
      }
  
  
      protected ServletContextAndPath getServletContextAndPathFromVirtualPath( String virtualPath ) throws IOException {
  	ServletContext servletContext = servlet.getServletContext();
  	String path = null;
  
  	if ( !virtualPath.startsWith("/") &&  !virtualPath.startsWith("\\") ) {
  	    path = getAbsolutePath( virtualPath );
  	} else {
  	    String normalized = SSIServletRequestUtil.normalize( virtualPath );
  	    if ( isVirtualWebappRelative ) {
  		path = normalized;
  	    } else {
  		servletContext = servletContext.getContext( normalized );
  		if ( servletContext == null ) {
  		    throw new IOException("Couldn't get context for path: " + normalized );
  		}
  
  		//If it's the root context, then there is no context element to remove, ie:
  		// '/file1.shtml' vs '/appName1/file1.shtml'
  		if ( !isRootContext( servletContext ) ) {
  		    path = getPathWithoutContext( normalized );
  		    if ( path == null ) {
  			throw new IOException("Couldn't remove context from path: " + normalized );
  		    }		    
  		} else {
  		    path = normalized;
  		}
  	    }
  	}
  	return new ServletContextAndPath( servletContext, path );
      }
  
      //Assumes servletContext is not-null
      //Assumes that identity comparison will be true for the same context
      //Assuming the above, getContext("/") will be non-null as long as the root context is accessible.
      //If it isn't, then servletContext can't be the root context anyway, hence they will not match.
      protected boolean isRootContext( ServletContext servletContext ) {
  	return servletContext == servletContext.getContext( "/" );
      }
  
      protected ServletContextAndPath getServletContextAndPath( String originalPath, boolean virtual ) throws IOException {
  	ServletContextAndPath csAndP = null;
  
  	if ( debug > 0 ) {
  	    log("SSIServletExternalResolver.getServletContextAndPath( " + originalPath + ", " + virtual + ")" , null);
  	}
  	if ( virtual ) {
  	    csAndP = getServletContextAndPathFromVirtualPath( originalPath );
  	} else {
  	    csAndP = getServletContextAndPathFromNonVirtualPath( originalPath );
  	}
  	return csAndP;
      }
  
      protected URLConnection getURLConnection( String originalPath, boolean virtual ) throws IOException {
  	ServletContextAndPath csAndP = getServletContextAndPath( originalPath, virtual );
  	ServletContext context = csAndP.getServletContext();
  	String path = csAndP.getPath();
  	   
  	URL url = context.getResource( path );
  	if ( url == null ) {
  	    throw new IOException("Context did not contain resource: " + path );
  	}
  	URLConnection urlConnection = url.openConnection();				    
  	return urlConnection;
      }
  
      public long getFileLastModified( String path, boolean virtual ) throws IOException {
  	long lastModified = 0;
  
  	URLConnection urlConnection = getURLConnection( path, virtual );
  	lastModified = urlConnection.getLastModified();
  	return lastModified;		
      }
  
      public long getFileSize( String path, boolean virtual ) throws IOException {
  	long fileSize = -1;
  
  	URLConnection urlConnection = getURLConnection( path, virtual );
  	fileSize = urlConnection.getContentLength();
  	return fileSize;
      }
  
      //We are making lots of unnecessary copies of the included data here.  If someone ever complains that this
      //is slow, we should connect the included stream to the print writer that SSICommand uses.
      public String getFileText( String originalPath, boolean virtual ) throws IOException {
  	try {
  	    ServletContextAndPath csAndP = getServletContextAndPath( originalPath, virtual );
  	    ServletContext context = csAndP.getServletContext();
  	    String path = csAndP.getPath();
  
  	    RequestDispatcher rd =
  		context.getRequestDispatcher( path );
  	    if ( rd == null ) {
  		throw new IOException("Couldn't get request dispatcher for path: " + path );
  	    }
  	    ByteArrayServletOutputStream basos = new ByteArrayServletOutputStream();
  	    ResponseIncludeWrapper responseIncludeWrapper =
  		new ResponseIncludeWrapper(res, basos );
  	    rd.include(req, responseIncludeWrapper );
  
  	    //We can't assume the included servlet flushed its output
  	    responseIncludeWrapper.flushOutputStreamOrWriter();
  	    byte[] bytes = basos.toByteArray();
  
  	    //Assume that the default encoding is what was used to encode the bytes. Questionable.
  	    String retVal = new String( bytes );
  
  	    //make an assumption that an empty response is a failure.  This is a problem if a truly empty file 
  	    //were included, but not sure how else to tell.
  	    if ( retVal.equals("") ) {
  		throw new IOException("Couldn't find file: " + path );
  	    }
  	    return retVal;
  	} catch (ServletException e) {
  	    throw new IOException("Couldn't include file: " + originalPath + " because of ServletException: " + e.getMessage() );
  	}
      }   
  
      protected class ServletContextAndPath {
  	protected ServletContext servletContext;
  	protected String path;
  
  	public ServletContextAndPath( ServletContext servletContext, String path ) {
  	    this.servletContext = servletContext;
  	    this.path = path;
  	}
  
  	public ServletContext getServletContext() {
  	    return servletContext;
  	}
  
  	public String getPath() {
  	    return path;
  	}
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIServletRequestUtil.java
  
  Index: SSIServletRequestUtil.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIServletRequestUtil.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.catalina.ssi;
  
  import javax.servlet.http.HttpServletRequest;
  import org.apache.catalina.util.RequestUtil;
  
  public class SSIServletRequestUtil {
      /**
       * Return the relative path associated with this servlet.
       *
       * Taken from DefaultServlet.java.  Perhaps this should be put in
       * org.apache.catalina.util somewhere?  Seems like it would be widely used.
       *
       * @param request The servlet request we are processing
       */
      public static String getRelativePath(HttpServletRequest request) {
  
          // Are we being processed by a RequestDispatcher.include()?
          if (request.getAttribute("javax.servlet.include.request_uri")!=null) {
              String result = (String)
                  request.getAttribute("javax.servlet.include.path_info");
              if (result == null)
                  result = (String)
                      request.getAttribute("javax.servlet.include.servlet_path");
              if ((result == null) || (result.equals("")))
                  result = "/";
              return (result);
          }
  
          // No, extract the desired path directly from the request
          String result = request.getPathInfo();
          if (result == null) {
              result = request.getServletPath();
          }
          if ((result == null) || (result.equals(""))) {
              result = "/";
          }
          return normalize(result);
      }
  
      /**
       * Return a context-relative path, beginning with a "/", that represents
       * the canonical version of the specified path after ".." and "." elements
       * are resolved out.  If the specified path attempts to go outside the
       * boundaries of the current context (i.e. too many ".." path elements
       * are present), return <code>null</code> instead.
       *
       * This normalize should be the same as DefaultServlet.normalize, which is almost the same
       * ( see source code below ) as RequestUtil.normalize.  Do we need all this duplication?
       *
       * @param path Path to be normalized
       */
      public static String normalize(String path) {
          if (path == null)
              return null;
  
  	String normalized = path;
  
  	//Why doesn't RequestUtil do this??
  
          // Normalize the slashes and add leading slash if necessary
          if ( normalized.indexOf('\\') >= 0 )
              normalized = normalized.replace( '\\', '/' );
  
  	normalized = RequestUtil.normalize( path );
  	return normalized;
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSISet.java
  
  Index: SSISet.java
  ===================================================================
  /*
   * SSISet.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSISet.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.catalina.ssi;
  
  
  import java.io.PrintWriter;
  
  /**
   * Implements the Server-side #set command
   *
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public class SSISet implements SSICommand {
      /**
       * @see SSICommand
       */
      public void process(SSIMediator ssiMediator,
  			String[] paramNames,
  			String[] paramValues,
  			PrintWriter writer) throws SSIStopProcessingException {
  
  	String errorMessage = ssiMediator.getConfigErrMsg();
  	String variableName = null;
  	for ( int i=0; i < paramNames.length; i++ ) {
  	    String paramName = paramNames[i];
  	    String paramValue = paramValues[i];
  
  	    if ( paramName.equalsIgnoreCase("var") ) {
  		variableName = paramValue;
  	    } else if ( paramName.equalsIgnoreCase("value") ) {
  		if ( variableName != null ) {
  		    ssiMediator.setVariableValue( variableName, paramValue );
  		} else {
  		    ssiMediator.log("#set--no variable specified");
  		    writer.write( errorMessage );
  		    throw new SSIStopProcessingException();
  		}
  	    } else {
  		ssiMediator.log("#set--Invalid attribute: " + paramName );
  		writer.write( errorMessage );
  		throw new SSIStopProcessingException();
  	    }
  	}
      }
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIStopProcessingException.java
  
  Index: SSIStopProcessingException.java
  ===================================================================
  /*
   * SSIStopProcessingException.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIStopProcessingException.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.catalina.ssi;
  
  /**
   * Exception used to tell SSIProcessor that it should stop processing SSI commands.
   * This is used to mimick the Apache behavior in #set with invalid attributes.
   *
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   */
  public class SSIStopProcessingException extends Exception {
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSiCommand.java
  
  Index: SSiCommand.java
  ===================================================================
  /*
   * SSICommand.java
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSiCommand.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/24 04:38:58 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.catalina.ssi;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  
  /**
   * The interface that all SSI commands ( SSIEcho, SSIInclude, ...) must implement.
   * 
   * @author Bip Thelin
   * @author Dan Sandberg
   * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
   *
   */
  public interface SSICommand {
      /**
       * Write the output of the command to the writer.
       *
       * @param ssiMediator the ssi mediator
       * @param paramNames The parameter names
       * @param paramValues The parameter values
       * @param writer the writer to output to
       * @throws SSIStopProcessingException if SSI processing should be aborted
       */
      public void process(SSIMediator ssiMediator,
  			String[] paramNames,
  			String[] paramValues,
  			PrintWriter writer) throws SSIStopProcessingException;
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/package.html
  
  Index: package.html
  ===================================================================
  <body>
  <p>This package contains code that is used by the SsiInvoker.</p>
  <p>This class consists of <code>SsiMediator.java</code> which works as a
  mediator between the different SsiCommands. To add a command you have to
  implement the <code>SsiCommand</code> interface and extend the
  <code>SsiMediator</code>. Commands currently implemented are</p>
  
  <ul>
  <li><b>SsiConfig</b> - Implementation of the NCSA command Config i.e. &lt;!--#config errmsg="error?"--&gt;</li>
  <li><b>SsiEcho</b> - Implementation of the NCSA command Echo i.e. &lt;!--#echo var="SERVER_NAME"--&gt;</li>
  <li><b>SsiExec</b> - Not implemented</li>
  <li><b>SsiFlastMod</b> - Implementation of the NCSA command flastmod i.e. &lt;!--#flastmod virtual="file"--&gt;</li>
  <li><b>SsiFsize</b> - Implementation of the NCSA command fsize i.e. &lt;!--#fsize file="file"--&gt;</li>
  <li><b>SsiInclude</b> - Implementation of the NCSA command Include i.e. &lt;!--#config virtual="includefile"--&gt;</li>
  </ul>
  </body>
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>