You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2001/09/29 06:36:35 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/modules/mappers DecodeInterceptor.java

costin      01/09/28 21:36:35

  Modified:    src/share/org/apache/tomcat/modules/mappers
                        DecodeInterceptor.java
  Log:
  Added code to normalize MessageBytes that were created as Strings.
  This fix a bug in JNI connector.
  
  In addition, added a note that will disable the decoding of the request, to be
  used with the server connector.
  
  Revision  Changes    Path
  1.9       +157 -15   jakarta-tomcat/src/share/org/apache/tomcat/modules/mappers/DecodeInterceptor.java
  
  Index: DecodeInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/mappers/DecodeInterceptor.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- DecodeInterceptor.java	2001/09/23 03:26:32	1.8
  +++ DecodeInterceptor.java	2001/09/29 04:36:35	1.9
  @@ -81,6 +81,9 @@
   
       // Note ids
       private int encodingInfoNote;
  +    // req.decoded - Is set after the request is decoded. The value is the
  +    // module that provided the decoding ( test for not null only )
  +    private int decodedNote;
       private int encodingSourceNote;
       private int sessionEncodingNote;
   
  @@ -139,6 +142,8 @@
   				  "req.encodingSource" );
   	sessionEncodingNote=cm.getNoteId(ContextManager.SESSION_NOTE,
   				  "session.encoding" );
  +	decodedNote=cm.getNoteId(ContextManager.REQUEST_NOTE,
  +				  "req.decoded" );
       }
       /* -------------------- Request mapping -------------------- */
   
  @@ -146,15 +151,38 @@
       // Based on Apache's path normalization code
       private void normalizePath(MessageBytes pathMB ) {
   	if( debug> 0 ) log( "Normalize " + pathMB.toString());
  -	if( pathMB.getType() != MessageBytes.T_BYTES ) return;
  -	
  -	ByteChunk bc=pathMB.getByteChunk();
  -					       
  +	if( pathMB.getType() == MessageBytes.T_BYTES ) {
  +	    boolean modified=normalize( pathMB.getByteChunk());
  +	    if( modified ) {
  +		pathMB.resetStringValue();
  +	    }
  +	} else if( pathMB.getType() == MessageBytes.T_CHARS ) {
  +	    String orig=pathMB.toString();
  +	    String str1=normalize( orig );
  +	    if( orig!=str1 ) {
  +		pathMB.resetStringValue();
  +		pathMB.setString( str1 );
  +	    }
  +	} else if( pathMB.getType() == MessageBytes.T_STR ) {
  +	    String orig=pathMB.toString();
  +	    String str1=normalize( orig );
  +	    if( orig!=str1 ) {
  +		pathMB.resetStringValue();
  +		pathMB.setString( str1 );
  +	    }
  +	}
  +
  +    }
  +
  +    private boolean normalize(  ByteChunk bc ) {
   	int start=bc.getStart();
   	int end=bc.getEnd();
   	byte buff[]=bc.getBytes();
   	int i=0;
   	int j=0;
  +	boolean modified=false;
  +	String orig=null;
  +	if( debug>0 ) orig=new String( buff, start, end-start);
   	
   	// remove //
   	for( i=start, j=start; i<end-1; i++ ) {
  @@ -167,9 +195,9 @@
   	    buff[j++]=buff[end-1];
   	    end=j;
   	    bc.setEnd( end );
  -	    pathMB.resetStringValue();
  +	    modified=true;
   	    if( debug > 0 ) {
  -		log( "Eliminate // " + pathMB.toString() + " " + start + " " + end );
  +		log( "Eliminate // " + orig + " " + start + " " + end );
   	    }
   	}
   	
  @@ -188,9 +216,9 @@
   	    buff[j++]=buff[end-1];
   	    end=j;
   	    bc.setEnd( end );
  -	    pathMB.resetStringValue();
  +	    modified=true;
   	    if( debug > 0 ) {
  -		log( "Eliminate /./ " + pathMB.toString());
  +		log( "Eliminate /./ " + orig);
   	    }
   	}
   	
  @@ -204,9 +232,9 @@
   	}
   	if( end!=j ) {
   	    bc.setEnd( end );
  -	    pathMB.resetStringValue();
  +	    modified=true;
   	    if( debug > 0 ) {
  -		log( "Eliminate ending /. " + pathMB.toString());
  +		log( "Eliminate ending /. " + orig);
   	    }
   	}
   
  @@ -232,9 +260,9 @@
   	    buff[j++]=buff[end-1];
   	    end=j;
   	    bc.setEnd( end );
  -	    pathMB.resetStringValue();
  +	    modified=true;
   	    if( debug > 0 ) {
  -		log( "Eliminate /../ " + pathMB.toString());
  +		log( "Eliminate /../ " + orig);
   	    }
   	}
   
  @@ -251,12 +279,122 @@
   	}
   	if( end!=j ) {
   	    bc.setEnd( end );
  -	    pathMB.resetStringValue();
  +	    modified=true;
   	    if( debug > 0 ) {
  -		log( "Eliminate ending /.. " + pathMB.toString());
  +		log( "Eliminate ending /.. " + orig);
   	    }
   	}
  +	return modified;
  +    }
  +
  +    private String normalize(  String str ) {
  +	int start=0;
  +	int end=str.length();
  +	char buff[]=str.toCharArray();
  +	int i=0;
  +	int j=0;
  +	boolean modified=false;
  +	String orig=str;
   	
  +	// remove //
  +	for( i=start, j=start; i<end-1; i++ ) {
  +	    if( buff[i]== '/' && buff[i+1]=='/' ) {
  +		while( buff[i+1]=='/' ) i++;
  +	    } 
  +	    buff[j++]=buff[i];
  +	}
  +	if( i!=j ) {
  +	    buff[j++]=buff[end-1];
  +	    end=j;
  +	    modified=true;
  +	    if( debug > 0 ) {
  +		log( "Eliminate // " + orig + " " + start + " " + end );
  +	    }
  +	}
  +	
  +	// remove /./
  +	for( i=start, j=start; i<end-1; i++ ) {
  +	    if( buff[i]== '.' && buff[i+1]=='/' &&
  +		( i==0 || buff[i-1]=='/' )) {
  +		// "/./"
  +		i+=1;
  +		if( i==end-1 ) j--; // cut the ending /
  +	    } else {
  +		buff[j++]=buff[i];
  +	    }
  +	}
  +	if( i!=j ) {
  +	    buff[j++]=buff[end-1];
  +	    end=j;
  +	    modified=true;
  +	    if( debug > 0 ) {
  +		log( "Eliminate /./ " + orig);
  +	    }
  +	}
  +	
  +	// remove  /. at the end
  +	j=end;
  +	if( end==start+1 && buff[start]== '.' )
  +	    end--;
  +	else if( end > start+1 && buff[ end-1 ] == '.' &&
  +		 buff[end-2]=='/' ) {
  +	    end=end-2;
  +	}
  +	if( end!=j ) {
  +	    modified=true;
  +	    if( debug > 0 ) {
  +		log( "Eliminate ending /. " + orig);
  +	    }
  +	}
  +
  +	// remove /../
  +	for( i=start, j=start; i<end-2; i++ ) {
  +	    if( buff[i] == '.' &&
  +		buff[i+1] == '.' &&
  +		buff[i+2]== '/' &&
  +		( i==0 || buff[ i-1 ] == '/' ) ) {
  +
  +		i+=1;
  +		// look for the previous /
  +	        j=j-2;
  +		while( j>0 && buff[j]!='/' ) {
  +		    j--;
  +		}
  +	    } else {
  +		buff[j++]=buff[i];
  +	    }
  +	}
  +	if( i!=j ) {
  +	    buff[j++]=buff[end-2];
  +	    buff[j++]=buff[end-1];
  +	    end=j;
  +	    modified=true;
  +	    if( debug > 0 ) {
  +		log( "Eliminate /../ " + orig);
  +	    }
  +	}
  +
  +
  +	// remove trailing xx/..
  +	j=end;
  +	if( end>start + 3 &&
  +	    buff[end-1]=='.' &&
  +	    buff[end-2]=='.' &&
  +	    buff[end-3]=='/' ) {
  +	    end-=4;
  +	    while( end>0 &&  buff[end]!='/' )
  +		end--; 
  +	}
  +	if( end!=j ) {
  +	    modified=true;
  +	    if( debug > 0 ) {
  +		log( "Eliminate ending /.. " +orig);
  +	    }
  +	}
  +	if( modified )
  +	    return new String( buff, 0, end );
  +	else
  +	    return str;
       }
   
       private boolean isSafeURI(MessageBytes pathMB) {
  @@ -375,7 +513,10 @@
   	    req.setCharEncoding( charEncoding );
   
   	// Decode request, save the original for the facade
  -	
  +
  +	// Already decoded
  +	if( req.getNote( decodedNote ) != null )
  +	    return 0;
   	if (pathMB.indexOf('%') >= 0 || pathMB.indexOf( '+' ) >= 0) {
   	    try {
   		req.unparsedURI().duplicate( pathMB );
  @@ -388,6 +529,7 @@
   		if( pathMB.indexOf( '\0' ) >=0 ) {
   		    return 404; // XXX should be 400 
   		}
  +		req.setNote( decodedNote, this );
   	    } catch( IOException ex ) {
   		log( "Error decoding request ", ex);
   		return 400;