You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Paul Speed <pa...@objectsciences.com> on 2002/11/25 22:56:16 UTC
Re: cvs commit: jakarta-tomcat-4.0/tester/web/golden
SSIConditional09.txt
Thanks Dan. Now I have my 15 milliseconds of fame back. ;)
I'll see if I can test the updates with my site soon.
-Paul Speed
dsandberg@apache.org wrote:
>
> dsandberg 2002/11/25 02:15:43
>
> Modified: catalina/src/share/org/apache/catalina/ssi SSICommand.java
> SSIConfig.java SSIEcho.java SSIExec.java
> SSIFlastmod.java SSIFsize.java SSIInclude.java
> SSIMediator.java SSIPrintenv.java SSIProcessor.java
> SSISet.java SSIStopProcessingException.java
> tester/src/bin tester.xml
> Added: catalina/src/share/org/apache/catalina/ssi
> ExpressionParseTree.java ExpressionTokenizer.java
> SSIConditional.java SSIConditionalState.java
> tester/web SSIConditional09.shtml
> tester/web/golden SSIConditional09.txt
> Log:
> Added back Paul Speed's conditional SSI enhancement. Updated code/regression tests to better emulate Apache SSI. Fixed bug w/ expression parser's handling of literals.
>
> Revision Changes Path
> 1.2 +5 -3 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSICommand.java
>
> Index: SSICommand.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSICommand.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- SSICommand.java 24 May 2002 16:35:39 -0000 1.1
> +++ SSICommand.java 25 Nov 2002 10:15:42 -0000 1.2
> @@ -79,12 +79,14 @@
> * Write the output of the command to the writer.
> *
> * @param ssiMediator the ssi mediator
> + * @param commandName the name of the actual command ( ie. echo )
> * @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 commandName,
> String[] paramNames,
> String[] paramValues,
> PrintWriter writer) throws SSIStopProcessingException;
>
>
>
> 1.3 +6 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIConfig.java
>
> Index: SSIConfig.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIConfig.java,v
> retrieving revision 1.2
> retrieving revision 1.3
> diff -u -r1.2 -r1.3
> --- SSIConfig.java 24 Nov 2002 06:22:36 -0000 1.2
> +++ SSIConfig.java 25 Nov 2002 10:15:42 -0000 1.3
> @@ -72,6 +72,7 @@
> * Implements the Server-side #exec command
> *
> * @author Bip Thelin
> + * @author Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> */
> @@ -80,6 +81,7 @@
> * @see SSICommand
> */
> public void process(SSIMediator ssiMediator,
> + String commandName,
> String[] paramNames,
> String[] paramValues,
> PrintWriter writer ) {
>
>
>
> 1.2 +6 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIEcho.java
>
> Index: SSIEcho.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIEcho.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- SSIEcho.java 24 May 2002 04:38:58 -0000 1.1
> +++ SSIEcho.java 25 Nov 2002 10:15:42 -0000 1.2
> @@ -71,6 +71,7 @@
> * Return the result associated with the supplied Server Variable.
> *
> * @author Bip Thelin
> + * @author Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> */
> @@ -82,6 +83,7 @@
> * @see SSICommand
> */
> public void process(SSIMediator ssiMediator,
> + String commandName,
> String[] paramNames,
> String[] paramValues,
> PrintWriter writer) {
>
>
>
> 1.3 +7 -5 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIExec.java
>
> Index: SSIExec.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIExec.java,v
> retrieving revision 1.2
> retrieving revision 1.3
> diff -u -r1.2 -r1.3
> --- SSIExec.java 24 Nov 2002 06:22:36 -0000 1.2
> +++ SSIExec.java 25 Nov 2002 10:15:42 -0000 1.3
> @@ -89,6 +89,7 @@
> *
> * @author Bip Thelin
> * @author Amy Roh
> + * @author Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> *
> @@ -101,6 +102,7 @@
> * @see SSICommand
> */
> public void process(SSIMediator ssiMediator,
> + String commandName,
> String[] paramNames,
> String[] paramValues,
> PrintWriter writer) {
> @@ -111,7 +113,7 @@
> String substitutedValue = ssiMediator.substituteVariables( paramValue );
>
> if ( paramName.equalsIgnoreCase("cgi") ) {
> - ssiInclude.process( ssiMediator, new String[] {"virtual"}, new String[] {substitutedValue}, writer );
> + ssiInclude.process( ssiMediator, "include", new String[] {"virtual"}, new String[] {substitutedValue}, writer );
> } else if ( paramName.equalsIgnoreCase("cmd") ) {
> boolean foundProgram = false;
> try {
>
>
>
> 1.3 +6 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIFlastmod.java
>
> Index: SSIFlastmod.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIFlastmod.java,v
> retrieving revision 1.2
> retrieving revision 1.3
> diff -u -r1.2 -r1.3
> --- SSIFlastmod.java 24 Nov 2002 06:22:36 -0000 1.2
> +++ SSIFlastmod.java 25 Nov 2002 10:15:42 -0000 1.3
> @@ -75,6 +75,7 @@
> * Implements the Server-side #flastmod command
> *
> * @author Bip Thelin
> + * @author Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> */
> @@ -83,6 +84,7 @@
> * @see SSICommand
> */
> public void process(SSIMediator ssiMediator,
> + String commandName,
> String[] paramNames,
> String[] paramValues,
> PrintWriter writer) {
>
>
>
> 1.4 +9 -7 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIFsize.java
>
> Index: SSIFsize.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/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 24 Nov 2002 06:22:36 -0000 1.3
> +++ SSIFsize.java 25 Nov 2002 10:15:42 -0000 1.4
> @@ -72,6 +72,7 @@
> * Implements the Server-side #fsize command
> *
> * @author Bip Thelin
> + * @author Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> */
> @@ -83,9 +84,10 @@
> * @see SSICommand
> */
> public void process(SSIMediator ssiMediator,
> - String[] paramNames,
> - String[] paramValues,
> - PrintWriter writer) {
> + String commandName,
> + String[] paramNames,
> + String[] paramValues,
> + PrintWriter writer) {
>
> String configErrMsg = ssiMediator.getConfigErrMsg();
> for(int i=0;i<paramNames.length;i++) {
>
>
>
> 1.3 +6 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIInclude.java
>
> Index: SSIInclude.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIInclude.java,v
> retrieving revision 1.2
> retrieving revision 1.3
> diff -u -r1.2 -r1.3
> --- SSIInclude.java 24 Nov 2002 06:22:36 -0000 1.2
> +++ SSIInclude.java 25 Nov 2002 10:15:42 -0000 1.3
> @@ -75,6 +75,7 @@
> * Implements the Server-side #include command
> *
> * @author Bip Thelin
> + * @author Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> */
> @@ -83,6 +84,7 @@
> * @see SSICommand
> */
> public void process(SSIMediator ssiMediator,
> + String commandName,
> String[] paramNames,
> String[] paramValues,
> PrintWriter writer) {
>
>
>
> 1.3 +10 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIMediator.java
>
> Index: SSIMediator.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIMediator.java,v
> retrieving revision 1.2
> retrieving revision 1.3
> diff -u -r1.2 -r1.3
> --- SSIMediator.java 24 Nov 2002 06:22:36 -0000 1.2
> +++ SSIMediator.java 25 Nov 2002 10:15:42 -0000 1.3
> @@ -86,6 +86,7 @@
> *
> * @author Bip Thelin
> * @author Amy Roh
> + * @author Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> */
> @@ -102,6 +103,7 @@
> protected Date lastModifiedDate;
> protected int debug;
> protected Strftime strftime;
> + protected SSIConditionalState conditionalState = new SSIConditionalState();
>
> static {
> //We try to encode only the same characters that apache does
> @@ -163,6 +165,10 @@
>
> public String getConfigSizeFmt() {
> return configSizeFmt;
> + }
> +
> + public SSIConditionalState getConditionalState() {
> + return conditionalState;
> }
>
> public Collection getVariableNames() {
>
>
>
> 1.2 +5 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIPrintenv.java
>
> Index: SSIPrintenv.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIPrintenv.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- SSIPrintenv.java 24 May 2002 04:38:58 -0000 1.1
> +++ SSIPrintenv.java 25 Nov 2002 10:15:42 -0000 1.2
> @@ -79,6 +79,7 @@
> * @see SSICommand
> */
> public void process(SSIMediator ssiMediator,
> + String commandName,
> String[] paramNames,
> String[] paramValues,
> PrintWriter writer) {
>
>
>
> 1.2 +82 -41 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIProcessor.java
>
> Index: SSIProcessor.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIProcessor.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- SSIProcessor.java 24 May 2002 04:38:58 -0000 1.1
> +++ SSIProcessor.java 25 Nov 2002 10:15:42 -0000 1.2
> @@ -108,6 +108,11 @@
> addCommand( "fsize", new SSIFsize() );
> addCommand( "printenv", new SSIPrintenv() );
> addCommand( "set", new SSISet() );
> + SSIConditional ssiConditional = new SSIConditional();
> + addCommand( "if", ssiConditional );
> + addCommand( "elif", ssiConditional );
> + addCommand( "endif", ssiConditional );
> + addCommand( "else", ssiConditional );
> }
>
> public void addCommand( String name, SSICommand command ) {
> @@ -147,7 +152,9 @@
> index += COMMAND_START.length();
> command.setLength( 0 ); //clear the command string
> } else {
> - writer.write( c );
> + if ( !ssiMediator.getConditionalState().processConditionalCommandsOnly ) {
> + writer.write( c );
> + }
> index++;
> }
> } else {
> @@ -159,20 +166,29 @@
> ssiExternalResolver.log( "SSIProcessor.process -- processing command: " + strCmd, null );
> }
> String[] paramNames = parseParamNames(command, strCmd.length());
> - String[] paramValues = parseParamValues(command, strCmd.length());
> + String[] paramValues = parseParamValues(command, strCmd.length(), paramNames.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 );
> - }
> + String errorMessage = null;
> + if ( ssiCommand == null ) {
> + errorMessage = "Unknown command: " + strCmd;
> + } else if ( paramValues == null ) {
> + errorMessage = "Error parsing directive parameters.";
> + } else if ( paramNames.length!=paramValues.length ) {
> + errorMessage = "Parameter names count does not match parameter values count on command: " + strCmd;
> } else {
> - ssiExternalResolver.log( "Unknown command: " + strCmd, null);
> + // don't process the command if we are processing conditional commands only and the
> + // command is not conditional
> + if ( !ssiMediator.getConditionalState().processConditionalCommandsOnly ||
> + ssiCommand instanceof SSIConditional ) {
> + ssiCommand.process( ssiMediator, strCmd, paramNames, paramValues, writer );
> + }
> + }
> +
> + if ( errorMessage != null ) {
> + ssiExternalResolver.log( errorMessage, null );
> writer.write( configErrMsg );
> }
> } else {
> @@ -214,20 +230,29 @@
> bIdx++;
> }
>
> - retBuf.append('"');
> + retBuf.append('=');
> inside=!inside;
> quotes=0;
>
> - while(bIdx < cmd.length()&"es!=2) {
> - if(cmd.charAt(bIdx)=='"')
> - quotes++;
> + boolean escaped=false;
> + for ( ; bIdx < cmd.length() && quotes != 2; bIdx++ ) {
> + char c = cmd.charAt(bIdx);
> +
> + // Need to skip escaped characters
> + if (c=='\\' && !escaped) {
> + escaped = true;
> + bIdx++;
> + continue;
> + }
> + escaped = false;
>
> - bIdx++;
> + if (c=='"')
> + quotes++;
> }
> }
> }
>
> - StringTokenizer str = new StringTokenizer(retBuf.toString(), "\"");
> + StringTokenizer str = new StringTokenizer(retBuf.toString(), "=");
> String[] retString = new String[str.countTokens()];
>
> while(str.hasMoreTokens()) {
> @@ -243,15 +268,14 @@
> * @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;
> + protected String[] parseParamValues(StringBuffer cmd, int start, int count) {
> + int valIndex = 0;
> boolean inside = false;
> - StringBuffer retBuf = new StringBuffer();
> + String[] vals = new String[count];
> + StringBuffer sb = new StringBuffer();
>
> - while(bIdx < cmd.length()) {
> - if(!inside) {
> + for (int bIdx = start; bIdx < cmd.length(); bIdx++ ) {
> + if (!inside) {
> while(bIdx < cmd.length()&&
> cmd.charAt(bIdx)!='"')
> bIdx++;
> @@ -261,26 +285,43 @@
>
> inside=!inside;
> } else {
> - while(bIdx < cmd.length() && cmd.charAt(bIdx)!='"') {
> - retBuf.append(cmd.charAt(bIdx));
> - bIdx++;
> - }
> + boolean escaped=false;
> + for ( ; bIdx < cmd.length(); bIdx++) {
>
> - retBuf.append('"');
> - inside=!inside;
> - }
> + char c = cmd.charAt(bIdx);
>
> - bIdx++;
> - }
> + // Check for escapes
> + if (c=='\\' && !escaped) {
> + escaped = true;
> + continue;
> + }
> +
> + // If we reach the other " then stop
> + if (c=='"' && !escaped)
> + break;
> +
> + // Since parsing of attributes and var
> + // substitution is done in separate places,
> + // we need to leave escape in the string
> + if (c=='$' && escaped)
> + sb.append( '\\' );
>
> - StringTokenizer str = new StringTokenizer(retBuf.toString(), "\"");
> - String[] retString = new String[str.countTokens()];
> + escaped = false;
> + sb.append(c);
> + }
>
> - while(str.hasMoreTokens()) {
> - retString[i++] = str.nextToken();
> + // If we hit the end without seeing a quote
> + // the signal an error
> + if (bIdx == cmd.length())
> + return null;
> +
> + vals[valIndex++] = sb.toString();
> + sb.delete( 0, sb.length() ); // clear the buffer
> + inside=!inside;
> + }
> }
>
> - return retString;
> + return vals;
> }
>
> /**
>
>
>
> 1.3 +10 -8 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSISet.java
>
> Index: SSISet.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSISet.java,v
> retrieving revision 1.2
> retrieving revision 1.3
> diff -u -r1.2 -r1.3
> --- SSISet.java 24 Nov 2002 06:22:36 -0000 1.2
> +++ SSISet.java 25 Nov 2002 10:15:42 -0000 1.3
> @@ -70,6 +70,7 @@
> /**
> * Implements the Server-side #set command
> *
> + * @author Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> */
> @@ -77,10 +78,11 @@
> /**
> * @see SSICommand
> */
> - public void process(SSIMediator ssiMediator,
> - String[] paramNames,
> - String[] paramValues,
> - PrintWriter writer) throws SSIStopProcessingException {
> + public void process( SSIMediator ssiMediator,
> + String commandName,
> + String[] paramNames,
> + String[] paramValues,
> + PrintWriter writer) throws SSIStopProcessingException {
>
> String errorMessage = ssiMediator.getConfigErrMsg();
> String variableName = null;
>
>
>
> 1.2 +5 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIStopProcessingException.java
>
> Index: SSIStopProcessingException.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIStopProcessingException.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- SSIStopProcessingException.java 24 May 2002 04:38:58 -0000 1.1
> +++ SSIStopProcessingException.java 25 Nov 2002 10:15:42 -0000 1.2
> @@ -67,6 +67,7 @@
> * 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 Paul Speed
> * @author Dan Sandberg
> * @version $Revision$, $Date$
> */
>
>
>
> 1.1 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/ExpressionParseTree.java
>
> Index: ExpressionParseTree.java
> ===================================================================
> /*
> * ExpressionParseTree.java
> * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/ExpressionParseTree.java,v 1.1 2002/11/25 10:15:42 dsandberg Exp $
> * $Revision: 1.1 $
> * $Date: 2002/11/25 10:15:42 $
> *
> * ====================================================================
> *
> * 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.util.LinkedList;
> import java.util.List;
> import java.text.ParseException;
>
> /**
> * Represents a parsed expression.
> *
> * @version $Revision: 1.1 $
> * @author Paul Speed
> */
> public class ExpressionParseTree
> {
> /**
> * Contains the current set of completed nodes. This
> * is a workspace for the parser.
> */
> private LinkedList nodeStack = new LinkedList();
>
> /**
> * Contains operator nodes that don't yet have values.
> * This is a workspace for the parser.
> */
> private LinkedList oppStack = new LinkedList();
>
> /**
> * The root node after the expression has been parsed.
> */
> private Node root;
>
> /**
> * The SSIMediator to use when evaluating the expressions.
> */
> private SSIMediator ssiMediator;
>
> /**
> * Creates a new parse tree for the specified expression.
> */
> public ExpressionParseTree( String expr,
> SSIMediator ssiMediator )
> throws ParseException {
> this.ssiMediator = ssiMediator;
> parseExpression( expr );
> }
>
> /**
> * Evaluates the tree and returns true or false. The specified
> * SSIMediator is used to resolve variable references.
> */
> public boolean evaluateTree() {
> return root.evaluate();
> }
>
> /**
> * Pushes a new operator onto the opp stack, resolving existing
> * opps as needed.
> */
> private void pushOpp( OppNode node ) {
>
> // If node is null then it's just a group marker
> if( node == null ) {
> oppStack.add( 0, node );
> return;
> }
>
> while (true) {
> if (oppStack.size() == 0)
> break;
> OppNode top = (OppNode)oppStack.get(0);
>
> // If the top is a spacer then don't pop
> // anything
> if (top == null)
> break;
>
> // If the top node has a lower precedence then
> // let it stay
> if (top.getPrecedence() < node.getPrecedence())
> break;
>
> // Remove the top node
> oppStack.remove(0);
>
> // Let it fill its branches
> top.popValues( nodeStack );
>
> // Stick it on the resolved node stack
> nodeStack.add( 0, top );
> }
>
> // Add the new node to the opp stack
> oppStack.add( 0, node );
> }
>
> /**
> * Resolves all pending opp nodes on the stack until the
> * next group marker is reached.
> */
> private void resolveGroup() {
>
> OppNode top = null;
> while ((top=(OppNode)oppStack.remove(0)) != null ) {
> // Let it fill its branches
> top.popValues( nodeStack );
>
> // Stick it on the resolved node stack
> nodeStack.add( 0, top );
> }
> }
>
> /**
> * Parses the specified expression into a tree of
> * parse nodes.
> */
> private void parseExpression( String expr ) throws ParseException {
>
> StringNode currStringNode = null;
>
> // We cheat a little and start an artificial
> // group right away. It makes finishing easier.
> pushOpp( null );
>
> ExpressionTokenizer et = new ExpressionTokenizer(expr);
> while (et.hasMoreTokens()) {
> int token = et.nextToken();
>
> if (token != ExpressionTokenizer.TOKEN_STRING)
> currStringNode = null;
>
> switch (token) {
> case ExpressionTokenizer.TOKEN_STRING:
> if (currStringNode == null) {
> currStringNode = new StringNode( et.getTokenValue() );
> nodeStack.add( 0, currStringNode );
> } else {
> // Add to the existing
> currStringNode.value.append( " " );
> currStringNode.value.append( et.getTokenValue() );
> }
> break;
> case ExpressionTokenizer.TOKEN_AND:
> pushOpp( new AndNode() );
> break;
> case ExpressionTokenizer.TOKEN_OR:
> pushOpp( new OrNode() );
> break;
> case ExpressionTokenizer.TOKEN_NOT:
> pushOpp( new NotNode() );
> break;
> case ExpressionTokenizer.TOKEN_EQ:
> pushOpp( new EqualNode() );
> break;
> case ExpressionTokenizer.TOKEN_NOT_EQ:
> pushOpp( new NotNode() );
> // Sneak the regular node in. The NOT will
> // be resolved when the next opp comes along.
> oppStack.add( 0, new EqualNode() );
> break;
> case ExpressionTokenizer.TOKEN_RBRACE:
> // Closeout the current group
> resolveGroup();
> break;
> case ExpressionTokenizer.TOKEN_LBRACE:
> // Push a group marker
> pushOpp( null );
> break;
> case ExpressionTokenizer.TOKEN_GE:
> pushOpp( new NotNode() );
> // Similar stategy to NOT_EQ above, except this
> // is NOT less than
> oppStack.add( 0, new LessThanNode() );
> break;
> case ExpressionTokenizer.TOKEN_LE:
> pushOpp( new NotNode() );
> // Similar stategy to NOT_EQ above, except this
> // is NOT greater than
> oppStack.add( 0, new GreaterThanNode() );
> break;
> case ExpressionTokenizer.TOKEN_GT:
> pushOpp( new GreaterThanNode() );
> break;
> case ExpressionTokenizer.TOKEN_LT:
> pushOpp( new LessThanNode() );
> break;
> case ExpressionTokenizer.TOKEN_END:
> break;
> }
> }
>
> // Finish off the rest of the opps
> resolveGroup();
>
> if (nodeStack.size() == 0) {
> throw new ParseException( "No nodes created.",
> et.getIndex() );
> }
> if (nodeStack.size() > 1) {
> throw new ParseException( "Extra nodes created.",
> et.getIndex() );
> }
> if (oppStack.size() != 0) {
> throw new ParseException( "Unused opp nodes exist.",
> et.getIndex() );
> }
>
> root = (Node)nodeStack.get(0);
> }
>
> /**
> * A node in the expression parse tree.
> */
> private abstract class Node {
>
> /**
> * Return true if the node evaluates to true.
> */
> public abstract boolean evaluate();
> }
>
> /**
> * A node the represents a String value
> */
> private class StringNode extends Node {
>
> StringBuffer value;
> String resolved = null;
>
> public StringNode( String value ) {
> this.value = new StringBuffer(value);
> }
>
> /**
> * Resolves any variable references and returns the
> * value string.
> */
> public String getValue() {
> if (resolved == null)
> resolved = ssiMediator.substituteVariables( value.toString() ) ;
> return resolved;
> }
>
> /**
> * Returns true if the string is not empty.
> */
> public boolean evaluate() {
> return !(getValue().length() == 0);
> }
>
> public String toString() {
> return value.toString();
> }
> }
>
> private static final int PRECEDENCE_NOT = 5;
> private static final int PRECEDENCE_COMPARE = 4;
> private static final int PRECEDENCE_LOGICAL = 1;
>
> /**
> * A node implementation that represents an operation.
> */
> private abstract class OppNode extends Node {
>
> /**
> * The left branch.
> */
> Node left;
>
> /**
> * The right branch.
> */
> Node right;
>
> /**
> * Returns a preference level suitable for comparison to
> * other OppNode preference levels.
> */
> public abstract int getPrecedence();
>
> /**
> * Lets the node pop its own branch nodes off the front of
> * the specified list. The default pulls two.
> */
> public void popValues( List values ) {
> right = (Node)values.remove(0);
> left = (Node)values.remove(0);
> }
> }
>
> private final class NotNode extends OppNode {
>
> public boolean evaluate() {
> return !left.evaluate();
> }
>
> public int getPrecedence() {
> return PRECEDENCE_NOT;
> }
>
> /**
> * Overridden to pop only one value.
> */
> public void popValues( List values ) {
> left = (Node)values.remove(0);
> }
>
> public String toString() {
> return left + " NOT";
> }
> }
>
> private final class AndNode extends OppNode {
>
> public boolean evaluate() {
> if (!left.evaluate()) // Short circuit
> return false;
> return right.evaluate();
> }
>
> public int getPrecedence() {
> return PRECEDENCE_LOGICAL;
> }
>
> public String toString() {
> return left + " " + right + " AND";
> }
> }
>
> private final class OrNode extends OppNode {
>
> public boolean evaluate() {
> if (left.evaluate()) // Short circuit
> return true;
> return right.evaluate();
> }
>
> public int getPrecedence() {
> return PRECEDENCE_LOGICAL;
> }
>
> public String toString() {
> return left + " " + right + " OR";
> }
> }
>
> private abstract class CompareNode extends OppNode {
> protected int compareBranches() {
> String val1 = ((StringNode)left).getValue();
> String val2 = ((StringNode)right).getValue();
> return val1.compareTo(val2);
> }
> }
>
> private final class EqualNode extends CompareNode {
>
> public boolean evaluate() {
> return (compareBranches() == 0);
> }
>
> public int getPrecedence() {
> return PRECEDENCE_COMPARE;
> }
>
> public String toString() {
> return left + " " + right + " EQ";
> }
> }
>
> private final class GreaterThanNode extends CompareNode {
>
> public boolean evaluate() {
> return (compareBranches() > 0);
> }
>
> public int getPrecedence() {
> return PRECEDENCE_COMPARE;
> }
>
> public String toString() {
> return left + " " + right + " GT";
> }
> }
>
> private final class LessThanNode extends CompareNode {
>
> public boolean evaluate() {
> return (compareBranches() < 0);
> }
>
> public int getPrecedence() {
> return PRECEDENCE_COMPARE;
> }
>
> public String toString() {
> return left + " " + right + " LT";
> }
> }
> }
>
>
>
> 1.1 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/ExpressionTokenizer.java
>
> Index: ExpressionTokenizer.java
> ===================================================================
> /*
> * ExpressionTokenizer.java
> * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/ExpressionTokenizer.java,v 1.1 2002/11/25 10:15:42 dsandberg Exp $
> * $Revision: 1.1 $
> * $Date: 2002/11/25 10:15:42 $
> *
> * ====================================================================
> *
> * 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;
>
> /**
> * Parses an expression string to return the individual tokens.
> * This is patterned similar to the StreamTokenizer in the JDK
> * but customized for SSI conditional expression parsing.
> *
> * @version $Revision: 1.1 $
> * @author Paul Speed
> */
> public class ExpressionTokenizer {
>
> public static final int TOKEN_STRING = 0;
> public static final int TOKEN_AND = 1;
> public static final int TOKEN_OR = 2;
> public static final int TOKEN_NOT = 3;
> public static final int TOKEN_EQ = 4;
> public static final int TOKEN_NOT_EQ = 5;
> public static final int TOKEN_RBRACE = 6;
> public static final int TOKEN_LBRACE = 7;
> public static final int TOKEN_GE = 8;
> public static final int TOKEN_LE = 9;
> public static final int TOKEN_GT = 10;
> public static final int TOKEN_LT = 11;
> public static final int TOKEN_END = 12;
>
> private char[] expr;
> private int tokenType = TOKEN_STRING;
> private String tokenVal = null;
> private int index;
> private int length;
>
> /**
> * Creates a new parser for the specified expression.
> */
> public ExpressionTokenizer( String expr ) {
> this.expr = expr.trim().toCharArray();
> this.length = this.expr.length;
> }
>
> /**
> * Returns true if there are more tokens.
> */
> public boolean hasMoreTokens() {
> return index < length;
> }
>
> /**
> * Returns the current index for error reporting purposes.
> */
> public int getIndex() {
> return index;
> }
>
> protected boolean isMetaChar( char c ) {
> return Character.isWhitespace( c ) ||
> c == '(' || c == ')' || c == '!' ||
> c == '<' || c == '>' || c == '|' ||
> c == '&' || c == '=';
> }
>
> /**
> * Returns the next token type and initializes any
> * state variables accordingly.
> */
> public int nextToken() {
> // Skip any leading white space
> while (index<length && Character.isWhitespace(expr[index]))
> index++;
>
> // Clear the current token val
> tokenVal = null;
>
> if (index == length)
> return TOKEN_END; // End of string
>
> int start = index;
> char currentChar = expr[index];
> char nextChar = (char)0;
> index++;
> if (index < length)
> nextChar = expr[index];
>
> // Check for a known token start
> switch (currentChar) {
> case '(':
> return TOKEN_LBRACE;
> case ')':
> return TOKEN_RBRACE;
> case '=':
> return TOKEN_EQ;
> case '!':
> if (nextChar == '=') {
> index++;
> return TOKEN_NOT_EQ;
> } else {
> return TOKEN_NOT;
> }
> case '|':
> if (nextChar == '|') {
> index++;
> return TOKEN_OR;
> }
> break;
> case '&':
> if (nextChar == '&') {
> index++;
> return TOKEN_AND;
> }
> break;
> case '>':
> if (nextChar == '=') {
> index++;
> return TOKEN_GE; // Greater than or equal
> } else {
> return TOKEN_GT; // Greater than
> }
> case '<':
> if (nextChar == '=') {
> index++;
> return TOKEN_LE; // Less than or equal
> } else {
> return TOKEN_LT; // Less than
> }
> default:
> // Otherwise it's a string
> break;
> }
>
> int end = index;
>
> // If it's a quoted string then end is the next unescaped quote
> if (currentChar == '"' || currentChar == '\'') {
> char endChar = currentChar;
> boolean escaped = false;
> start++;
> for ( ; index < length; index++) {
> if (expr[index] == '\\' && !escaped) {
> escaped = true;
> continue;
> }
> if (expr[index] == endChar && !escaped)
> break;
>
> escaped = false;
> }
> end = index;
> index++; // Skip the end quote
> } else {
> // End is the next whitespace character
> for ( ; index < length; index++) {
> if ( isMetaChar(expr[index]) )
> break;
> }
> end = index;
> }
>
> // Extract the string from the array
> this.tokenVal = new String( expr, start, end - start );
>
> return TOKEN_STRING;
> }
>
> /**
> * Returns the String value of the token if it was type
> * TOKEN_STRING. Otherwise null is returned.
> */
> public String getTokenValue() {
> return tokenVal;
> }
> }
>
>
>
> 1.1 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIConditional.java
>
> Index: SSIConditional.java
> ===================================================================
> /*
> * SSIConditional.java
> * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIConditional.java,v 1.1 2002/11/25 10:15:42 dsandberg Exp $
> * $Revision: 1.1 $
> * $Date: 2002/11/25 10:15:42 $
> *
> * ====================================================================
> *
> * 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.text.ParseException;
> import java.util.LinkedList;
> import java.util.List;
>
> import javax.servlet.ServletOutputStream;
>
> /**
> * SSI command that handles all conditional directives.
> *
> * @version $Revision: 1.1 $
> * @author Paul Speed
> */
> public class SSIConditional implements SSICommand {
> /**
> * @see SSICommand
> */
> public void process( SSIMediator ssiMediator,
> String commandName,
> String[] paramNames,
> String[] paramValues,
> PrintWriter writer) throws SSIStopProcessingException {
>
> // Retrieve the current state information
> SSIConditionalState state = ssiMediator.getConditionalState();
>
> if ( "if".equalsIgnoreCase( commandName ) ) {
> // Do nothing if we are nested in a false branch
> // except count it
> if ( state.processConditionalCommandsOnly ) {
> state.nestingCount++;
> return;
> }
>
> state.nestingCount = 0;
>
> // Evaluate the expression
> if ( evaluateArguments(paramNames, paramValues, ssiMediator) ) {
> // No more branches can be taken for this if block
> state.branchTaken = true;
> } else {
> // Do not process this branch
> state.processConditionalCommandsOnly = true;
> state.branchTaken = false;
> }
>
> } else if ( "elif".equalsIgnoreCase( commandName ) ) {
> // No need to even execute if we are nested in
> // a false branch
> if (state.nestingCount > 0)
> return;
>
> // If a branch was already taken in this if block
> // then disable output and return
> if ( state.branchTaken ) {
> state.processConditionalCommandsOnly = true;
> return;
> }
>
> // Evaluate the expression
> if ( evaluateArguments(paramNames, paramValues, ssiMediator) ) {
> // Turn back on output and mark the branch
> state.processConditionalCommandsOnly = false;
> state.branchTaken = true;
> } else {
> // Do not process this branch
> state.processConditionalCommandsOnly = true;
> state.branchTaken = false;
> }
>
> } else if ( "else".equalsIgnoreCase( commandName ) ) {
> // No need to even execute if we are nested in
> // a false branch
> if (state.nestingCount > 0)
> return;
>
> // If we've already taken another branch then
> // disable output otherwise enable it.
> state.processConditionalCommandsOnly = state.branchTaken;
>
> // And in any case, it's safe to say a branch
> // has been taken.
> state.branchTaken = true;
>
> } else if ( "endif".equalsIgnoreCase( commandName ) ) {
> // If we are nested inside a false branch then pop out
> // one level on the nesting count
> if (state.nestingCount > 0) {
> state.nestingCount--;
> return;
> }
>
> // Turn output back on
> state.processConditionalCommandsOnly = false;
>
> // Reset the branch status for any outer if blocks,
> // since clearly we took a branch to have gotten here
> // in the first place.
> state.branchTaken = true;
> } else {
> throw new SSIStopProcessingException();
> //throw new SsiCommandException( "Not a conditional command:" + cmdName );
> }
> }
>
> /**
> * Retrieves the expression from the specified arguments
> * and peforms the necessary evaluation steps.
> */
> private boolean evaluateArguments( String[] names,
> String[] values,
> SSIMediator ssiMediator ) throws SSIStopProcessingException {
> String expr = getExpression( names, values );
> if (expr == null) {
> throw new SSIStopProcessingException();
> //throw new SsiCommandException( "No expression specified." );
> }
>
> try {
> ExpressionParseTree tree = new ExpressionParseTree( expr,
> ssiMediator );
> return tree.evaluateTree();
> } catch (ParseException e) {
> //throw new SsiCommandException( "Error parsing expression." );
> throw new SSIStopProcessingException();
> }
> }
>
> /**
> * Returns the "expr" if the arg name is appropriate, otherwise
> * returns null.
> */
> private String getExpression( String[] paramNames, String[] paramValues ) {
> if ( "expr".equalsIgnoreCase( paramNames[0]) )
> return paramValues[0];
> return null;
> }
> }
>
>
>
> 1.1 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIConditionalState.java
>
> Index: SSIConditionalState.java
> ===================================================================
> /*
> * SSIConditionalState.java
> * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIConditionalState.java,v 1.1 2002/11/25 10:15:42 dsandberg Exp $
> * $Revision: 1.1 $
> * $Date: 2002/11/25 10:15:42 $
> *
> * ====================================================================
> *
> * 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;
>
> /**
> * This class is used by SSIMediator and SSIConditional to keep track of state information necessary to process
> * the nested conditional commands ( if, elif, else, endif ).
> *
> * @version $Revision: 1.1 $
> * @author Dan Sandberg
> * @author Paul Speed
> */
> class SSIConditionalState {
> /**
> * Set to true if the current conditional has already been
> * completed, i.e.: a branch was taken.
> */
> boolean branchTaken = false;
>
> /**
> * Counts the number of nested false branches.
> */
> int nestingCount = 0;
>
> /**
> * Set to true if only conditional commands ( if, elif, else, endif ) should be processed.
> */
> boolean processConditionalCommandsOnly = false;
> }
>
>
>
> 1.85 +36 -0 jakarta-tomcat-4.0/tester/src/bin/tester.xml
>
> Index: tester.xml
> ===================================================================
> RCS file: /home/cvs/jakarta-tomcat-4.0/tester/src/bin/tester.xml,v
> retrieving revision 1.84
> retrieving revision 1.85
> diff -u -r1.84 -r1.85
> --- tester.xml 24 Nov 2002 06:22:36 -0000 1.84
> +++ tester.xml 25 Nov 2002 10:15:43 -0000 1.85
> @@ -1849,6 +1849,42 @@
> golden="${golden.path}/SSIFsize02.txt"/>
>
> <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional01.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional01.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional02.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional02.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional03.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional03.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional04.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional04.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional05.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional05.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional06.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional06.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional07.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional07.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional08.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional08.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> + request="${context.path}/SSIConditional09.shtml" debug="${debug}"
> + golden="${golden.path}/SSIConditional09.txt"/>
> +
> + <tester host="${host}" port="${port}" protocol="${protocol}"
> request="${context.path}/SSIVarSub01.shtml" debug="${debug}"
> golden="${golden.path}/SSIVarSub01.txt"/>
>
>
>
>
> 1.1 jakarta-tomcat-4.0/tester/web/SSIConditional09.shtml
>
> Index: SSIConditional09.shtml
> ===================================================================
> 1
> <!--#if expr="1=2" -->
> a
> ##<!--#if expr="1=2" -->
> b
> ##<!--#else -->
> c
> ##<!--#endif -->
> d
> <!--#elif expr="2=2" -->
> e
> ##<!--#if expr="2=2" -->
> f
> ####<!--#if expr="1=2" -->
> **11
> ####<!--#elif expr="2=3" -->
> **22
> ####<!--#endif -->
> **33
> ##<!--#else -->
> g
> ##<!--#endif -->
> h
> <!--#else -->
> i
> ##<!--#if expr="1=1" -->
> j
> ##<!--#else -->
> k
> ##<!--#endif -->
> l
> <!--#endif -->
> #
> now we test extra #endif commands
> <!--#endif -->
> n
> <!--#endif -->
> o
>
>
> 1.1 jakarta-tomcat-4.0/tester/web/golden/SSIConditional09.txt
>
> Index: SSIConditional09.txt
> ===================================================================
> 1
>
> e
> ##
> f
> ####
> **33
> ##
> h
>
> #
> now we test extra #endif commands
>
> n
>
> o
>
>
>
> --
> To unsubscribe, e-mail: <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>