markt       2005/04/23 03:22:37

  Modified:    catalina/src/conf web.xml
               catalina/src/share/org/apache/catalina/ssi
                        ResponseIncludeWrapper.java SSICommand.java
                        SSIConditional.java SSIConfig.java SSIEcho.java
                        SSIExec.java SSIFlastmod.java SSIFsize.java
                        SSIInclude.java SSIMediator.java SSIPrintenv.java
                        SSIProcessor.java SSIServlet.java
                        SSIServletExternalResolver.java SSISet.java
               webapps/docs changelog.xml ssi-howto.xml
  Log:
  Provide an ServletFilter implementation of Server Side Includes (SSI). This 
was submitted by David Becker under bug
   33106.
  
  Revision  Changes    Path
  1.57      +79 -0     jakarta-tomcat-catalina/catalina/src/conf/web.xml
  
  Index: web.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/conf/web.xml,v
  retrieving revision 1.56
  retrieving revision 1.57
  diff -u -r1.56 -r1.57
  --- web.xml   4 Apr 2005 20:57:02 -0000       1.56
  +++ web.xml   23 Apr 2005 10:22:37 -0000      1.57
  @@ -206,6 +206,9 @@
       </servlet>
   
   
  +  <!-- NOTE: An SSI Filter is also available as an alternative SSI          
-->
  +  <!-- implementation. Use either the Servlet or the Filter but NOT both.   
-->
  +  <!--                                                                      
-->
     <!-- Server Side Includes processing servlet, which processes SSI         
-->
     <!-- directives in HTML pages consistent with similar support in web      
-->
     <!-- servers like Apache.  Traditionally, this servlet is mapped to the   
-->
  @@ -362,6 +365,78 @@
   -->
   
   
  +  <!-- ================== Built In Filter Definitions ===================== 
-->
  +
  +  <!-- NOTE: An SSI Servlet is also available as an alternative SSI         
-->
  +  <!-- implementation. Use either the Servlet or the Filter but NOT both.   
-->
  +  <!--                                                                      
-->
  +  <!-- Server Side Includes processing filter, which processes SSI          
-->
  +  <!-- directives in HTML pages consistent with similar support in web      
-->
  +  <!-- servers like Apache.  Traditionally, this filter is mapped to the    
-->
  +  <!-- URL pattern "*.shtml", though it can be mapped to "*" as it will     
-->
  +  <!-- selectively enable/disable SSI processing based on mime types.  The  
-->
  +  <!-- contentType init param allows you to apply SSI processing to JSP     
-->
  +  <!-- pages, javascript, or any other content you wish.  This filter       
-->
  +  <!-- supports the following initialization parameters (default values are 
-->
  +  <!-- in square brackets):                                                 
-->
  +  <!--                                                                      
-->
  +  <!--   contentType         A regex pattern that must be matched before    
-->
  +  <!--                       SSI processing is applied.                     
-->
  +  <!--                       [text/x-server-parsed-html(;.*)?]              
-->
  +  <!--                                                                      
-->
  +  <!--   debug               Debugging detail level for messages logged     
-->
  +  <!--                       by this servlet.  [0]                          
-->
  +  <!--                                                                      
-->
  +  <!--   expires             The number of seconds before a page with SSI   
-->
  +  <!--                       directives will expire.  [No default]          
-->
  +  <!--                                                                      
-->
  +  <!--   isVirtualWebappRelative                                            
-->
  +  <!--                       Should "virtual" paths be interpreted as       
-->
  +  <!--                       relative to the context root, instead of       
-->
  +  <!--                       the server root?  (0=false, 1=true) [0]        
-->
  +  <!--                                                                      
-->
  +  <!--                                                                      
-->
  +  <!-- IMPORTANT: To use the SSI filter, you also need to rename the        
-->
  +  <!--            $CATALINA_HOME/server/lib/servlets-ssi.renametojar file   
-->
  +  <!--            to $CATALINA_HOME/server/lib/servlets-ssi.jar             
-->
  +
  +<!--
  +    <filter>
  +        <filter-name>ssi</filter-name>
  +        <filter-class>
  +          org.apache.catalina.ssi.SSIFilter
  +        </filter-class>
  +        <init-param>
  +          <param-name>contentType</param-name>
  +          <param-value>text/x-server-parsed-html(;.*)?</param-value>
  +        </init-param>
  +        <init-param>
  +          <param-name>debug</param-name>
  +          <param-value>0</param-value>
  +        </init-param>
  +        <init-param>
  +          <param-name>expires</param-name>
  +          <param-value>666</param-value>
  +        </init-param>
  +        <init-param>
  +          <param-name>isVirtualWebappRelative</param-name>
  +          <param-value>0</param-value>
  +        </init-param>
  +    </filter>
  +-->
  +
  +
  +  <!-- ==================== Built In Filter Mappings ====================== 
-->
  +
  +  <!-- The mapping for the SSI Filter -->
  +<!--
  +    <filter-mapping>
  +        <filter-name>ssi</filter-name>
  +        <url-pattern>*.shtml</url-pattern>
  +    </filter-mapping>
  +-->
  +
  +
     <!-- ==================== Default Session Configuration ================= 
-->
     <!-- You can set the default session timeout (in minutes) for all newly   
-->
     <!-- created sessions by modifying the value below.                       
-->
  @@ -783,6 +858,10 @@
           <mime-type>application/x-shar</mime-type>
       </mime-mapping>
       <mime-mapping>
  +        <extension>shtml</extension>
  +        <mime-type>text/x-server-parsed-html</mime-type>
  +    </mime-mapping>
  +    <mime-mapping>
           <extension>smf</extension>
           <mime-type>audio/x-midi</mime-type>
       </mime-mapping>
  
  
  
  1.6       +135 -8    
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/ResponseIncludeWrapper.java
  
  Index: ResponseIncludeWrapper.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/ResponseIncludeWrapper.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ResponseIncludeWrapper.java       1 Sep 2004 18:33:33 -0000       1.5
  +++ ResponseIncludeWrapper.java       23 Apr 2005 10:22:37 -0000      1.6
  @@ -13,23 +13,40 @@
   
   import java.io.IOException;
   import java.io.PrintWriter;
  +
  +import javax.servlet.ServletContext;
   import javax.servlet.ServletOutputStream;
  +import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
   import javax.servlet.http.HttpServletResponseWrapper;
  +
  +import org.apache.catalina.util.DateTool;
   /**
    * A HttpServletResponseWrapper, used from
    * <code>SSIServletExternalResolver</code>
    * 
    * @author Bip Thelin
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class ResponseIncludeWrapper extends HttpServletResponseWrapper {
       /**
  +     * The names of some headers we want to capture.
  +     */
  +     private static final String CONTENT_TYPE = "content-type";
  +    private static final String LAST_MODIFIED = "last-modified";
  +    protected long lastModified = -1;
  +    private String contentType = null;
  +
  +    /**
        * Our ServletOutputStream
        */
  -    protected ServletOutputStream originalServletOutputStream;
  +    protected ServletOutputStream captureServletOutputStream;
       protected ServletOutputStream servletOutputStream;
       protected PrintWriter printWriter;
  +    
  +     private ServletContext context;
  +     private HttpServletRequest request;
   
   
       /**
  @@ -41,10 +58,13 @@
        * @param out
        *            The ServletOutputStream' to use
        */
  -    public ResponseIncludeWrapper(HttpServletResponse res,
  -            ServletOutputStream originalServletOutputStream) {
  -        super(res);
  -        this.originalServletOutputStream = originalServletOutputStream;
  +    public ResponseIncludeWrapper(ServletContext context, 
  +             HttpServletRequest request, HttpServletResponse response,
  +           ServletOutputStream captureServletOutputStream) {
  +        super(response);
  +        this.context = context;
  +        this.request = request;
  +        this.captureServletOutputStream = captureServletOutputStream;
       }
   
   
  @@ -74,7 +94,7 @@
       public PrintWriter getWriter() throws java.io.IOException {
           if (servletOutputStream == null) {
               if (printWriter == null) {
  -                printWriter = new PrintWriter(originalServletOutputStream);
  +                printWriter = new PrintWriter(captureServletOutputStream);
               }
               return printWriter;
           }
  @@ -93,10 +113,117 @@
       public ServletOutputStream getOutputStream() throws java.io.IOException {
           if (printWriter == null) {
               if (servletOutputStream == null) {
  -                servletOutputStream = originalServletOutputStream;
  +                servletOutputStream = captureServletOutputStream;
               }
               return servletOutputStream;
           }
           throw new IllegalStateException();
       }
  +    
  +    
  +    /**
  +     * Returns the value of the <code>last-modified</code> header field. The
  +     * result is the number of milliseconds since January 1, 1970 GMT.
  +     *
  +     * @return the date the resource referenced by this
  +     *   <code>ResponseIncludeWrapper</code> was last modified, or -1 if not
  +     *   known.                                                             
  +     */
  +    public long getLastModified() {                                          
                                                                                
                                 
  +        if (lastModified == -1) {
  +            // javadocs say to return -1 if date not known, if you want 
another
  +            // default, put it here
  +            return -1;
  +        }
  +        return lastModified;
  +    }
  +
  +    /**
  +     * Sets the value of the <code>last-modified</code> header field.
  +     *
  +     * @param value The number of milliseconds since January 1, 1970 GMT.
  +     */
  +    public void setLastModified(long lastModified) {
  +        this.lastModified = lastModified;
  +        ((HttpServletResponse) getResponse()).setDateHeader(LAST_MODIFIED,
  +                lastModified);
  +    }
  +
  +    /**
  +     * Returns the value of the <code>content-type</code> header field.
  +     *
  +     * @return the content type of the resource referenced by this
  +     *   <code>ResponseIncludeWrapper</code>, or <code>null</code> if not 
known.
  +     */
  +    public String getContentType() {
  +        if (contentType == null) {
  +            String url = request.getRequestURI();
  +            String mime = context.getMimeType(url);
  +            if (mime != null)
  +            {
  +                setContentType(mime);
  +            }
  +            else
  +            {
  +             // return a safe value
  +               setContentType("application/x-octet-stream");
  +            }
  +        }
  +        return contentType;
  +    }
  +    
  +    /**
  +     * Sets the value of the <code>content-type</code> header field.
  +     *
  +     * @param mime a mime type
  +     */
  +    public void setContentType(String mime) {
  +        contentType = mime;
  +        if (contentType != null) {
  +            getResponse().setContentType(contentType);
  +        }
  +    }
  +
  +
  +    public void addDateHeader(String name, long value) {
  +        super.addDateHeader(name, value);
  +        String lname = name.toLowerCase();
  +        if (lname.equals(LAST_MODIFIED)) {
  +            lastModified = value;
  +        }
  +    }
  +
  +    public void addHeader(String name, String value) {
  +        super.addHeader(name, value);
  +        String lname = name.toLowerCase();
  +        if (lname.equals(LAST_MODIFIED)) {
  +            try {
  +                lastModified = DateTool.rfc1123Format.parse(value).getTime();
  +            } catch (Throwable ignore) { }
  +        } else if (lname.equals(CONTENT_TYPE)) {
  +            contentType = value;
  +        }
  +    }
  +
  +    public void setDateHeader(String name, long value) {
  +        super.setDateHeader(name, value);
  +        String lname = name.toLowerCase();
  +        if (lname.equals(LAST_MODIFIED)) {
  +            lastModified = value;
  +        }
  +    }
  +
  +    public void setHeader(String name, String value) {
  +        super.setHeader(name, value);
  +        String lname = name.toLowerCase();
  +        if (lname.equals(LAST_MODIFIED)) {
  +            try {
  +                lastModified = DateTool.rfc1123Format.parse(value).getTime();
  +            } catch (Throwable ignore) { }
  +        }
  +        else if (lname.equals(CONTENT_TYPE))
  +        {
  +            contentType = value;
  +        }
  +    }
   }
  \ No newline at end of file
  
  
  
  1.5       +4 -2      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSICommand.java
  
  Index: SSICommand.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSICommand.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SSICommand.java   1 Sep 2004 18:33:33 -0000       1.4
  +++ SSICommand.java   23 Apr 2005 10:22:37 -0000      1.5
  @@ -18,6 +18,7 @@
    * 
    * @author Bip Thelin
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public interface SSICommand {
  @@ -34,10 +35,11 @@
        *            The parameter values
        * @param writer
        *            the writer to output to
  +     * @return the most current modified date resulting from any SSI commands
        * @throws SSIStopProcessingException
        *             if SSI processing should be aborted
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +     public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer)
               throws SSIStopProcessingException;
   }
  \ No newline at end of file
  
  
  
  1.3       +11 -7     
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIConditional.java
  
  Index: SSIConditional.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIConditional.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SSIConditional.java       1 Sep 2004 18:33:33 -0000       1.2
  +++ SSIConditional.java       23 Apr 2005 10:22:37 -0000      1.3
  @@ -18,14 +18,17 @@
    * 
    * @version $Revision$
    * @author Paul Speed
  + * @author David Becker
    */
   public class SSIConditional implements SSICommand {
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer)
               throws SSIStopProcessingException {
  +     // Assume anything using conditionals was modified by it
  +     long lastModified = System.currentTimeMillis();
           // Retrieve the current state information
           SSIConditionalState state = ssiMediator.getConditionalState();
           if ("if".equalsIgnoreCase(commandName)) {
  @@ -33,7 +36,7 @@
               // except count it
               if (state.processConditionalCommandsOnly) {
                   state.nestingCount++;
  -                return;
  +                return lastModified;
               }
               state.nestingCount = 0;
               // Evaluate the expression
  @@ -48,12 +51,12 @@
           } else if ("elif".equalsIgnoreCase(commandName)) {
               // No need to even execute if we are nested in
               // a false branch
  -            if (state.nestingCount > 0) return;
  +            if (state.nestingCount > 0) return lastModified;
               // If a branch was already taken in this if block
               // then disable output and return
               if (state.branchTaken) {
                   state.processConditionalCommandsOnly = true;
  -                return;
  +                return lastModified;
               }
               // Evaluate the expression
               if (evaluateArguments(paramNames, paramValues, ssiMediator)) {
  @@ -68,7 +71,7 @@
           } else if ("else".equalsIgnoreCase(commandName)) {
               // No need to even execute if we are nested in
               // a false branch
  -            if (state.nestingCount > 0) return;
  +            if (state.nestingCount > 0) return lastModified;
               // If we've already taken another branch then
               // disable output otherwise enable it.
               state.processConditionalCommandsOnly = state.branchTaken;
  @@ -80,7 +83,7 @@
               // one level on the nesting count
               if (state.nestingCount > 0) {
                   state.nestingCount--;
  -                return;
  +                return lastModified;
               }
               // Turn output back on
               state.processConditionalCommandsOnly = false;
  @@ -93,6 +96,7 @@
               //throw new SsiCommandException( "Not a conditional command:" +
               // cmdName );
           }
  +        return lastModified;
       }
   
   
  
  
  
  1.5       +5 -2      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIConfig.java
  
  Index: SSIConfig.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIConfig.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SSIConfig.java    1 Sep 2004 18:33:33 -0000       1.4
  +++ SSIConfig.java    23 Apr 2005 10:22:37 -0000      1.5
  @@ -18,13 +18,14 @@
    * @author Bip Thelin
    * @author Paul Speed
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public final class SSIConfig implements SSICommand {
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer) {
           for (int i = 0; i < paramNames.length; i++) {
               String paramName = paramNames[i];
  @@ -46,5 +47,7 @@
                   writer.write(configErrMsg);
               }
           }
  +        // Setting config options doesn't really change the page
  +        return 0;
       }
   }
  \ No newline at end of file
  
  
  
  1.4       +6 -2      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIEcho.java
  
  Index: SSIEcho.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIEcho.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SSIEcho.java      1 Sep 2004 18:33:33 -0000       1.3
  +++ SSIEcho.java      23 Apr 2005 10:22:37 -0000      1.4
  @@ -18,6 +18,7 @@
    * @author Bip Thelin
    * @author Paul Speed
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class SSIEcho implements SSICommand {
  @@ -28,8 +29,9 @@
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer) {
  +     long lastModified = 0;
           String encoding = DEFAULT_ENCODING;
           String errorMessage = ssiMediator.getConfigErrMsg();
           for (int i = 0; i < paramNames.length; i++) {
  @@ -42,6 +44,7 @@
                       variableValue = MISSING_VARIABLE_VALUE;
                   }
                   writer.write(variableValue);
  +                lastModified = System.currentTimeMillis();
               } else if (paramName.equalsIgnoreCase("encoding")) {
                   if (isValidEncoding(paramValue)) {
                       encoding = paramValue;
  @@ -54,6 +57,7 @@
                   writer.write(errorMessage);
               }
           }
  +        return lastModified;
       }
   
   
  
  
  
  1.5       +9 -5      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIExec.java
  
  Index: SSIExec.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIExec.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SSIExec.java      1 Sep 2004 18:33:33 -0000       1.4
  +++ SSIExec.java      23 Apr 2005 10:22:37 -0000      1.5
  @@ -23,6 +23,7 @@
    * @author Amy Roh
    * @author Paul Speed
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class SSIExec implements SSICommand {
  @@ -33,16 +34,17 @@
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer) {
  +        long lastModified = 0;
           String configErrMsg = ssiMediator.getConfigErrMsg();
           String paramName = paramNames[0];
           String paramValue = paramValues[0];
           String substitutedValue = 
ssiMediator.substituteVariables(paramValue);
           if (paramName.equalsIgnoreCase("cgi")) {
  -            ssiInclude.process(ssiMediator, "include",
  -                    new String[]{"virtual"}, new String[]{substitutedValue},
  -                    writer);
  +            lastModified = ssiInclude.process(ssiMediator, "include",
  +                                     new String[]{"virtual"}, new 
String[]{substitutedValue},
  +                                                             writer);
           } else if (paramName.equalsIgnoreCase("cmd")) {
               boolean foundProgram = false;
               try {
  @@ -57,6 +59,7 @@
                   IOTools.flow(stdErrReader, writer, buf);
                   IOTools.flow(stdOutReader, writer, buf);
                   proc.waitFor();
  +                lastModified = System.currentTimeMillis();                
               } catch (InterruptedException e) {
                   ssiMediator.log("Couldn't exec file: " + substitutedValue, 
e);
                   writer.write(configErrMsg);
  @@ -68,5 +71,6 @@
                   ssiMediator.log("Couldn't exec file: " + substitutedValue, 
e);
               }
           }
  +        return lastModified;
       }
   }
  \ No newline at end of file
  
  
  
  1.5       +6 -3      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIFlastmod.java
  
  Index: SSIFlastmod.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIFlastmod.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SSIFlastmod.java  1 Sep 2004 18:33:33 -0000       1.4
  +++ SSIFlastmod.java  23 Apr 2005 10:22:37 -0000      1.5
  @@ -22,14 +22,16 @@
    * @author Bip Thelin
    * @author Paul Speed
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public final class SSIFlastmod implements SSICommand {
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer) {
  +     long lastModified = 0;
           String configErrMsg = ssiMediator.getConfigErrMsg();
           StringBuffer buf = new StringBuffer();
           for (int i = 0; i < paramNames.length; i++) {
  @@ -41,7 +43,7 @@
                   if (paramName.equalsIgnoreCase("file")
                           || paramName.equalsIgnoreCase("virtual")) {
                       boolean virtual = paramName.equalsIgnoreCase("virtual");
  -                    long lastModified = ssiMediator.getFileLastModified(
  +                    lastModified = ssiMediator.getFileLastModified(
                               substitutedValue, virtual);
                       Date date = new Date(lastModified);
                       String configTimeFmt = ssiMediator.getConfigTimeFmt();
  @@ -58,6 +60,7 @@
                   writer.write(configErrMsg);
               }
           }
  +        return lastModified;
       }
   
   
  
  
  
  1.4       +7 -2      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIFsize.java
  
  Index: SSIFsize.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIFsize.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SSIFsize.java     1 Sep 2004 18:33:33 -0000       1.3
  +++ SSIFsize.java     23 Apr 2005 10:22:37 -0000      1.4
  @@ -20,6 +20,7 @@
    * @author Bip Thelin
    * @author Paul Speed
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public final class SSIFsize implements SSICommand {
  @@ -30,8 +31,9 @@
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer) {
  +        long lastModified = 0;
           String configErrMsg = ssiMediator.getConfigErrMsg();
           for (int i = 0; i < paramNames.length; i++) {
               String paramName = paramNames[i];
  @@ -42,6 +44,8 @@
                   if (paramName.equalsIgnoreCase("file")
                           || paramName.equalsIgnoreCase("virtual")) {
                       boolean virtual = paramName.equalsIgnoreCase("virtual");
  +                    lastModified = ssiMediator.getFileLastModified(
  +                            substitutedValue, virtual);
                       long size = ssiMediator.getFileSize(substitutedValue,
                               virtual);
                       String configSizeFmt = ssiMediator.getConfigSizeFmt();
  @@ -56,6 +60,7 @@
                   writer.write(configErrMsg);
               }
           }
  +        return lastModified;
       }
   
   
  
  
  
  1.5       +7 -2      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIInclude.java
  
  Index: SSIInclude.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIInclude.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SSIInclude.java   1 Sep 2004 18:33:33 -0000       1.4
  +++ SSIInclude.java   23 Apr 2005 10:22:37 -0000      1.5
  @@ -19,14 +19,16 @@
    * @author Bip Thelin
    * @author Paul Speed
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public final class SSIInclude implements SSICommand {
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer) {
  +        long lastModified = 0;
           String configErrMsg = ssiMediator.getConfigErrMsg();
           for (int i = 0; i < paramNames.length; i++) {
               String paramName = paramNames[i];
  @@ -37,6 +39,8 @@
                   if (paramName.equalsIgnoreCase("file")
                           || paramName.equalsIgnoreCase("virtual")) {
                       boolean virtual = paramName.equalsIgnoreCase("virtual");
  +                    lastModified = ssiMediator.getFileLastModified(
  +                              substitutedValue, virtual);
                       String text = ssiMediator.getFileText(substitutedValue,
                               virtual);
                       writer.write(text);
  @@ -51,5 +55,6 @@
                   writer.write(configErrMsg);
               }
           }
  +        return lastModified;
       }
   }
  \ No newline at end of file
  
  
  
  1.5       +5 -4      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIMediator.java
  
  Index: SSIMediator.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIMediator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SSIMediator.java  1 Sep 2004 18:33:33 -0000       1.4
  +++ SSIMediator.java  23 Apr 2005 10:22:37 -0000      1.5
  @@ -29,6 +29,7 @@
    * @author Amy Roh
    * @author Paul Speed
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class SSIMediator {
  @@ -41,7 +42,7 @@
       protected String configSizeFmt = DEFAULT_CONFIG_SIZE_FMT;
       protected String className = getClass().getName();
       protected SSIExternalResolver ssiExternalResolver;
  -    protected Date lastModifiedDate;
  +    protected long lastModifiedDate;
       protected int debug;
       protected Strftime strftime;
       protected SSIConditionalState conditionalState = new 
SSIConditionalState();
  @@ -64,7 +65,7 @@
   
   
       public SSIMediator(SSIExternalResolver ssiExternalResolver,
  -            Date lastModifiedDate, int debug) {
  +            long lastModifiedDate, int debug) {
           this.ssiExternalResolver = ssiExternalResolver;
           this.lastModifiedDate = lastModifiedDate;
           this.debug = debug;
  @@ -315,7 +316,7 @@
               setVariableValue("DATE_LOCAL", null);
               ssiExternalResolver.setVariableValue(className + ".DATE_LOCAL",
                       retVal);
  -            retVal = formatDate(lastModifiedDate, null);
  +            retVal = formatDate(new Date(lastModifiedDate), null);
               setVariableValue("LAST_MODIFIED", null);
               ssiExternalResolver.setVariableValue(className + 
".LAST_MODIFIED",
                       retVal);
  
  
  
  1.4       +7 -3      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIPrintenv.java
  
  Index: SSIPrintenv.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIPrintenv.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SSIPrintenv.java  1 Sep 2004 18:33:33 -0000       1.3
  +++ SSIPrintenv.java  23 Apr 2005 10:22:37 -0000      1.4
  @@ -18,14 +18,16 @@
    * Implements the Server-side #printenv command
    * 
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class SSIPrintenv implements SSICommand {
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer) {
  +     long lastModified = 0;
           //any arguments should produce an error
           if (paramNames.length > 0) {
               String errorMessage = ssiMediator.getConfigErrMsg();
  @@ -46,7 +48,9 @@
                   writer.write('=');
                   writer.write(variableValue);
                   writer.write('\n');
  +                lastModified = System.currentTimeMillis();
               }
           }
  +        return lastModified;
       }
  -}
  \ No newline at end of file
  +}
  
  
  
  1.5       +10 -5     
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIProcessor.java
  
  Index: SSIProcessor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIProcessor.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SSIProcessor.java 1 Sep 2004 18:33:33 -0000       1.4
  +++ SSIProcessor.java 23 Apr 2005 10:22:37 -0000      1.5
  @@ -15,7 +15,6 @@
   import java.io.PrintWriter;
   import java.io.Reader;
   import java.io.StringWriter;
  -import java.util.Date;
   import java.util.HashMap;
   import java.util.StringTokenizer;
   import org.apache.catalina.util.IOTools;
  @@ -25,6 +24,7 @@
    * necessary[
    * 
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class SSIProcessor {
  @@ -76,11 +76,12 @@
        *            the reader to read the file containing SSIs from
        * @param writer
        *            the writer to write the file with the SSIs processed.
  +     * @return the most current modified date resulting from any SSI commands
        * @throws IOException
        *             when things go horribly awry. Should be unlikely since the
        *             SSICommand usually catches 'normal' IOExceptions.
        */
  -    public void process(Reader reader, Date lastModifiedDate,
  +    public long process(Reader reader, long lastModifiedDate,
               PrintWriter writer) throws IOException {
           SSIMediator ssiMediator = new SSIMediator(ssiExternalResolver,
                   lastModifiedDate, debug);
  @@ -142,8 +143,11 @@
                               // command is not conditional
                               if 
(!ssiMediator.getConditionalState().processConditionalCommandsOnly
                                       || ssiCommand instanceof SSIConditional) 
{
  -                                ssiCommand.process(ssiMediator, strCmd,
  -                                        paramNames, paramValues, writer);
  +                                long lmd = ssiCommand.process(ssiMediator, 
strCmd,
  +                                               paramNames, paramValues, 
writer);
  +                                if (lmd > lastModifiedDate) {
  +                                    lastModifiedDate = lmd;
  +                                }                                    
                               }
                           }
                           if (errorMessage != null) {
  @@ -160,6 +164,7 @@
               //If we are here, then we have already stopped processing, so all
               // is good
           }
  +        return lastModifiedDate;
       }
   
   
  
  
  
  1.10      +10 -6     
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIServlet.java
  
  Index: SSIServlet.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIServlet.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- SSIServlet.java   4 Apr 2005 20:57:02 -0000       1.9
  +++ SSIServlet.java   23 Apr 2005 10:22:37 -0000      1.10
  @@ -19,7 +19,6 @@
   import java.io.StringWriter;
   import java.net.URL;
   import java.net.URLConnection;
  -import java.util.Date;
   import javax.servlet.ServletContext;
   import javax.servlet.ServletException;
   import javax.servlet.http.HttpServlet;
  @@ -33,6 +32,7 @@
    * @author Bip Thelin
    * @author Amy Roh
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class SSIServlet extends HttpServlet {
  @@ -190,8 +190,9 @@
   
       protected void processSSI(HttpServletRequest req, HttpServletResponse 
res,
               URL resource) throws IOException {
  -        SSIExternalResolver ssiExternalResolver = new 
SSIServletExternalResolver(
  -                this, req, res, isVirtualWebappRelative, debug, 
inputEncoding);
  +        SSIExternalResolver ssiExternalResolver =
  +            new SSIServletExternalResolver(getServletContext(), req, res,
  +                    isVirtualWebappRelative, debug, inputEncoding);
           SSIProcessor ssiProcessor = new SSIProcessor(ssiExternalResolver,
                   debug);
           PrintWriter printWriter = null;
  @@ -217,8 +218,11 @@
           }
           BufferedReader bufferedReader = new BufferedReader(isr);
   
  -        Date lastModifiedDate = new Date(resourceInfo.getLastModified());
  -        ssiProcessor.process(bufferedReader, lastModifiedDate, printWriter);
  +        long lastModified = ssiProcessor.process(bufferedReader,
  +                resourceInfo.getLastModified(), printWriter);
  +        if (lastModified > 0) {
  +            res.setDateHeader("last-modified", lastModified);
  +        }
           if (buffered) {
               printWriter.flush();
               String text = stringWriter.toString();
  
  
  
  1.6       +54 -25    
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIServletExternalResolver.java
  
  Index: SSIServletExternalResolver.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSIServletExternalResolver.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- SSIServletExternalResolver.java   4 Apr 2005 20:57:02 -0000       1.5
  +++ SSIServletExternalResolver.java   23 Apr 2005 10:22:37 -0000      1.6
  @@ -12,6 +12,7 @@
   
   
   import java.io.IOException;
  +import java.io.UnsupportedEncodingException;
   import java.net.URL;
   import java.net.URLConnection;
   import java.net.URLDecoder;
  @@ -21,13 +22,15 @@
   import javax.servlet.RequestDispatcher;
   import javax.servlet.ServletContext;
   import javax.servlet.ServletException;
  -import javax.servlet.http.HttpServlet;
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
  +import org.apache.catalina.connector.Request;
  +
   /**
    * An implementation of SSIExternalResolver that is used with servlets.
    * 
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class SSIServletExternalResolver implements SSIExternalResolver {
  @@ -37,17 +40,17 @@
               "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 ServletContext context;
       protected HttpServletRequest req;
       protected HttpServletResponse res;
       protected boolean isVirtualWebappRelative;
       protected int debug;
       protected String inputEncoding;
   
  -    public SSIServletExternalResolver(HttpServlet servlet,
  +    public SSIServletExternalResolver(ServletContext context,
               HttpServletRequest req, HttpServletResponse res,
               boolean isVirtualWebappRelative, int debug, String 
inputEncoding) {
  -        this.servlet = servlet;
  +        this.context = context;
           this.req = req;
           this.res = res;
           this.isVirtualWebappRelative = isVirtualWebappRelative;
  @@ -61,9 +64,9 @@
           //is the same as Servlet.log( message ), since API
           //doesn't seem to say so.
           if (throwable != null) {
  -            servlet.log(message, throwable);
  +            context.log(message, throwable);
           } else {
  -            servlet.log(message);
  +            context.log(message);
           }
       }
   
  @@ -161,7 +164,35 @@
           } else if (name.equalsIgnoreCase("QUERY_STRING_UNESCAPED")) {
               String queryString = req.getQueryString();
               if (queryString != null) {
  -                retVal = URLDecoder.decode(queryString);
  +                // Use default as a last resort
  +             String queryStringEncoding =
  +                    org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING;
  +                
  +                String uriEncoding = null;
  +                boolean useBodyEncodingForURI = false;
  +                
  +                // Get encoding settings from request / connector if possible
  +                String requestEncoding = req.getCharacterEncoding();
  +                if (req instanceof Request) {
  +                    uriEncoding = 
((Request)req).getConnector().getURIEncoding();
  +                    useBodyEncodingForURI =
  +                        
((Request)req).getConnector().getUseBodyEncodingForURI();
  +                }
  +                
  +                // If valid, apply settings from request / connector
  +                if (uriEncoding != null) {
  +                     queryStringEncoding = uriEncoding;
  +                } else if(useBodyEncodingForURI) {
  +                    if (requestEncoding != null) {
  +                     queryStringEncoding = requestEncoding;
  +                    }
  +                }
  +                
  +                try {
  +                         retVal = URLDecoder.decode(queryString, 
queryStringEncoding);                       
  +                             } catch (UnsupportedEncodingException e) {
  +                                     retVal = queryString;
  +                             }
               }
           } else if (name.equalsIgnoreCase("REMOTE_ADDR")) {
               retVal = req.getRemoteAddr();
  @@ -180,8 +211,7 @@
           } else if (name.equalsIgnoreCase("SERVER_PROTOCOL")) {
               retVal = req.getProtocol();
           } else if (name.equalsIgnoreCase("SERVER_SOFTWARE")) {
  -            ServletContext servletContext = servlet.getServletContext();
  -            retVal = servletContext.getServerInfo();
  +            retVal = context.getServerInfo();
           }
           return retVal;
       }
  @@ -251,26 +281,24 @@
                       + nonVirtualPath);
           }
           String path = getAbsolutePath(nonVirtualPath);
  -        ServletContext servletContext = servlet.getServletContext();
           ServletContextAndPath csAndP = new ServletContextAndPath(
  -                servletContext, path);
  +                context, 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);
  +            return new ServletContextAndPath(context, 
getAbsolutePath(virtualPath));
           } else {
               String normalized = SSIServletRequestUtil.normalize(virtualPath);
               if (isVirtualWebappRelative) {
  -                path = normalized;
  +                return new ServletContextAndPath(context, normalized);
               } else {
  -                servletContext = servletContext.getContext(normalized);
  -                if (servletContext == null) {
  +                ServletContext normContext = context.getContext(normalized);
  +                if (normContext == null) {
                       throw new IOException("Couldn't get context for path: "
                               + normalized);
                   }
  @@ -278,19 +306,19 @@
                   // to remove,
                   // ie:
                   // '/file1.shtml' vs '/appName1/file1.shtml'
  -                if (!isRootContext(servletContext)) {
  -                    path = getPathWithoutContext(normalized);
  -                    if (path == null) {
  +                if (!isRootContext(normContext)) {
  +                    String noContext = getPathWithoutContext(normalized);
  +                    if (noContext == null) {
                           throw new IOException(
                                   "Couldn't remove context from path: "
                                           + normalized);
                       }
  +                    return new ServletContextAndPath(normContext, noContext);
                   } else {
  -                    path = normalized;
  +                    return new ServletContextAndPath(normContext, 
normalized);
                   }
               }
           }
  -        return new ServletContextAndPath(servletContext, path);
       }
   
   
  @@ -370,9 +398,10 @@
                   throw new IOException(
                           "Couldn't get request dispatcher for path: " + path);
               }
  -            ByteArrayServletOutputStream basos = new 
ByteArrayServletOutputStream();
  -            ResponseIncludeWrapper responseIncludeWrapper = new 
ResponseIncludeWrapper(
  -                    res, basos);
  +            ByteArrayServletOutputStream basos =
  +                new ByteArrayServletOutputStream();
  +            ResponseIncludeWrapper responseIncludeWrapper =
  +                new ResponseIncludeWrapper(context, req, res, basos);
               rd.include(req, responseIncludeWrapper);
               //We can't assume the included servlet flushed its output
               responseIncludeWrapper.flushOutputStreamOrWriter();
  
  
  
  1.4       +6 -2      
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSISet.java
  
  Index: SSISet.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/ssi/SSISet.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SSISet.java       1 Sep 2004 18:33:33 -0000       1.3
  +++ SSISet.java       23 Apr 2005 10:22:37 -0000      1.4
  @@ -17,15 +17,17 @@
    * 
    * @author Paul Speed
    * @author Dan Sandberg
  + * @author David Becker
    * @version $Revision$, $Date$
    */
   public class SSISet implements SSICommand {
       /**
        * @see SSICommand
        */
  -    public void process(SSIMediator ssiMediator, String commandName,
  +    public long process(SSIMediator ssiMediator, String commandName,
               String[] paramNames, String[] paramValues, PrintWriter writer)
               throws SSIStopProcessingException {
  +        long lastModified = 0;
           String errorMessage = ssiMediator.getConfigErrMsg();
           String variableName = null;
           for (int i = 0; i < paramNames.length; i++) {
  @@ -39,6 +41,7 @@
                               .substituteVariables(paramValue);
                       ssiMediator.setVariableValue(variableName,
                               substitutedValue);
  +                    lastModified = System.currentTimeMillis();
                   } else {
                       ssiMediator.log("#set--no variable specified");
                       writer.write(errorMessage);
  @@ -50,5 +53,6 @@
                   throw new SSIStopProcessingException();
               }
           }
  +        return lastModified;
       }
   }
  \ No newline at end of file
  
  
  
  1.292     +4 -0      jakarta-tomcat-catalina/webapps/docs/changelog.xml
  
  Index: changelog.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/webapps/docs/changelog.xml,v
  retrieving revision 1.291
  retrieving revision 1.292
  diff -u -r1.291 -r1.292
  --- changelog.xml     22 Apr 2005 20:38:38 -0000      1.291
  +++ changelog.xml     23 Apr 2005 10:22:37 -0000      1.292
  @@ -99,6 +99,10 @@
           Remove CopyParentClassLoader rule, which doesn't seem to be doing 
anything useful
           anymore. (remm)
         </fix>
  +      <add>
  +        Provide an ServletFilter implementation of Server Side Includes 
(SSI). This was
  +        submitted by David Becker under <bug>33106</bug>. (markt)
  +      </add>
       </changelog>
     </subsection>
     
  
  
  
  1.4       +41 -4     jakarta-tomcat-catalina/webapps/docs/ssi-howto.xml
  
  Index: ssi-howto.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/webapps/docs/ssi-howto.xml,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ssi-howto.xml     4 Apr 2005 20:57:02 -0000       1.3
  +++ ssi-howto.xml     23 Apr 2005 10:22:37 -0000      1.4
  @@ -29,10 +29,19 @@
   <a href="http://httpd.apache.org/docs/howto/ssi.html#basicssidirectives";>
   Apache Introduction to SSI</a> for information on using SSI directives.</p>
   
  -<p>SSI support is implemented using the servlet class
  +<p>SSI support is available as a servlet and as a filter. You should use one
  +or the other to provide SSI support but not both.</p>
  +
  +<p>Servlet based SSI support is implemented using the class
   <code>org.apache.catalina.ssi.SSIServlet</code>.  Traditionally, this servlet
   is mapped to the URL pattern "*.shtml".</p>
   
  +<p>Filter based SSI support is implemented using the class
  +<code>org.apache.catalina.ssi.SSIFilter</code>.  Traditionally, this filter
  +is mapped to the URL pattern "*.shtml", though it can be mapped to "*" as
  +it will selectively enable/disable SSI processing based on mime types.  The
  +contentType init param allows you to apply SSI processing to JSP pages,
  +javascript, or any other content you wish.</p>
   <p>By default SSI support is disabled in Tomcat.</p>
   </section>
   
  @@ -46,11 +55,17 @@
   <p>Rename <code>$CATALINA_BASE/server/lib/servlets-ssi.renametojar</code>
   to <code>$CATALINA_BASE/server/lib/servlets-ssi.jar</code>.</p>
   
  -<p>Remove the XML comments from around the SSI servlet and servlet-mapping
  -configuration in <code>$CATALINA_BASE/conf/web.xml</code>.</p>
  +<p>To use the SSI servlet, remove the XML comments from around the SSI 
servlet
  +and servlet-mapping configuration in
  +<code>$CATALINA_BASE/conf/web.xml</code>.</p>
  +
  +<p>To use the SSI filter, remove the XML comments from around the SSI filter
  +and filter-mapping configuration in
  +<code>$CATALINA_BASE/conf/web.xml</code>.</p>
  +
   </section>
   
  -<section name="Configuration">
  +<section name="Servlet Configuration">
   
   <p>There are several servlet init parameters which can be used to
   configure the behaviour of the SSI servlet.
  @@ -75,6 +90,28 @@
   
   </section>
   
  +<section name="Filter Configuration">
  +
  +<p>There are several filter init parameters which can be used to
  +configure the behaviour of the SSI filter.
  +<ul>
  +<li><strong>contentType</strong> - A regex pattern that must be matched 
before
  +SSI processing is applied. When crafting your own pattern, don't forget that 
a
  +mime content type may be followed by an optional character set in the form
  +"mime/type; charset=set" that you must take into account.  Default is
  +"text/x-server-parsed-html(;.*)?".</li>
  +<li><strong>debug</strong> - Debugging detail level for messages logged
  +by this servlet. Default 0.</li>
  +<li><strong>expires</strong> - The number of seconds before a page with SSI
  +directives will expire. Default behaviour is for all SSI directives to be
  +evaluated for every request.</li>
  +<li><strong>isVirtualWebappRelative</strong> - Should "virtual" SSI directive
  +paths be interpreted as relative to the context root, instead of the server
  +root? (0=false, 1=true) Default 0 (false).</li>
  +</ul>
  +</p>
  +
  +</section>
   </body>
   
   </document>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to