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/05/26 19:24:17 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util/http Parameters.java

costin      01/05/26 10:24:17

  Modified:    src/share/org/apache/tomcat/util/http Parameters.java
  Log:
  Few big changes here...
  
  The "new" code is now in use ( has been here for few months, but we kept
  using the old code for safety ). The most important thing is that
  now we corectly decode ( if charset is provided ) - the old code didn't.
  
  There is still some old code in use ( only used by RequestDispatcher), but
  the common code is now fixed.
  
  Revision  Changes    Path
  1.12      +182 -84   jakarta-tomcat/src/share/org/apache/tomcat/util/http/Parameters.java
  
  Index: Parameters.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/http/Parameters.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- Parameters.java	2001/02/20 03:14:11	1.11
  +++ Parameters.java	2001/05/26 17:24:17	1.12
  @@ -59,9 +59,7 @@
   
   package org.apache.tomcat.util.http;
   
  -import  org.apache.tomcat.util.buf.MessageBytes;
  -import  org.apache.tomcat.util.buf.CharChunk;
  -import  org.apache.tomcat.util.buf.ByteChunk;
  +import  org.apache.tomcat.util.buf.*;
   import  org.apache.tomcat.util.collections.MultiMap;
   import java.io.*;
   import java.util.*;
  @@ -72,6 +70,7 @@
    * @author Costin Manolache
    */
   public final class Parameters extends MultiMap {
  +
       // Transition: we'll use the same Hashtable( String->String[] )
       // for the beginning. When we are sure all accesses happen through
       // this class - we can switch to MultiMap
  @@ -81,6 +80,9 @@
       
       MessageBytes queryMB;
       MimeHeaders  headers;
  +
  +    UDecoder urlDec;
  +    MessageBytes decodedQuery=new MessageBytes();
       
       public static final int INITIAL_SIZE=4;
   
  @@ -94,6 +96,8 @@
       private Parameters parent=null;
       private Parameters currentChild=null;
   
  +    String encoding=null;
  +    
       /**
        * 
        */
  @@ -109,12 +113,18 @@
   	this.headers=headers;
       }
   
  +    public void setEncoding( String s ) {
  +	encoding=s;
  +    }
  +
       public void recycle() {
   	super.recycle();
   	paramHashStringArray.clear();
   	didQueryParameters=false;
   	currentChild=null;
   	didMerge=false;
  +	encoding=null;
  +	decodedQuery.recycle();
       }
       
       // -------------------- Sub-request support --------------------
  @@ -145,11 +155,13 @@
   	// set child to null !
   	if( currentChild==null ) {
   	    currentChild=new Parameters();
  +	    currentChild.setURLDecoder( urlDec );
   	    currentChild.parent=this;
   	    return;
   	}
   	if( currentChild.child==null ) {
   	    currentChild.child=new Parameters();
  +	    currentChild.setURLDecoder( urlDec );
   	    currentChild.child.parent=currentChild;
   	} // it is not null if this object already had a child
   	// i.e. a deeper include() ( we keep it )
  @@ -205,9 +217,10 @@
        */
       private void merge() {
   	// recursive
  -	//	System.out.println("Merging " + this + " with " +
  -	// parent + " " + didMerge);
  -	//System.out.println( "Before " + paramsAsString());
  +	if( debug > 0 ) {
  +	    log("Before merging " + this + " " + parent + " " + didMerge );
  +	    log(  paramsAsString());
  +	}
   	// Local parameters first - they take precedence as in spec.
   	handleQueryParameters();
   
  @@ -222,7 +235,8 @@
   	Hashtable parentProps=parent.paramHashStringArray;
   	merge2( paramHashStringArray , parentProps);
   	didMerge=true;
  -	//System.out.println( "After " + paramsAsString());
  +	if(debug > 0 )
  +	    log("After " + paramsAsString());
       }
   
   
  @@ -231,54 +245,34 @@
   	String[] values = getParameterValues(name);
           if (values != null) {
   	    if( values.length==0 ) return "";
  -	    //System.out.println("XXX " + name + "=" + values[0] );
               return values[0];
           } else {
  -	    //	    System.out.println("XXX " + name + "=null" );
   	    return null;
           }
       }
       // -------------------- Processing --------------------
  -
       /** Process the query string into parameters
        */
       public void handleQueryParameters() {
   	if( didQueryParameters ) return;
   	
   	didQueryParameters=true;
  -	if( queryMB==null )
  +	if( debug > 0  )
  +	    log( "Decoding query " + queryMB + " " + encoding);
  +	    
  +	if( queryMB==null || queryMB.isNull() )
   	    return;
  -	String qString=queryMB.toString();
  -	if(qString!=null) {
  -	    processFormData( qString );
  -	}
  -    }
  -
  -    public void processParameters(String data) {
  -	processFormData( data );
  -    }
  -    
  -    // XXX ENCODING !!
  -    public void processData(byte data[]) {
  -	// make sure the request line query is processed
  -	handleQueryParameters();
   	
   	try {
  -	    String postedBody = new String(data, 0, data.length,
  -					   "8859_1");
  -	    // XXX encoding !!!
  -
  -	    processFormData( postedBody );
  -	    
  -	    //Hashtable postParameters=new Hashtable();
  -	    //Parameters.processFormData( postedBody, postParameters);
  -	    //	    Parameters.merge2(paramHashStringArray,  postParameters);
  -
  -	} catch( UnsupportedEncodingException ex ) {
  -	    //	    return postParameters;
  +	    decodedQuery.duplicate( queryMB );
  +	} catch( IOException ex ) {
   	}
  +	if( debug > 0  )
  +	    log( "Decoding query " + decodedQuery + " " + encoding);
  +
  +	processParameters( decodedQuery );
       }
  -    
  +
       // --------------------
       
       /** Combine 2 hashtables into a new one.
  @@ -315,51 +309,50 @@
   	}
       }
   
  -    // XXX XXX Optimize
  -    private void processFormData(String data) {
  -        // there's got to be a faster way of doing this.
  -	if( data==null ) return; // no parameters
  -	
  -        StringTokenizer tok = new StringTokenizer(data, "&", false);
  -        while (tok.hasMoreTokens()) {
  -            String pair = tok.nextToken();
  -	    int pos = pair.indexOf('=');
  -	    if (pos != -1) {
  -		String key = CharChunk.unescapeURL(pair.substring(0, pos));
  -		String value = CharChunk.unescapeURL(pair.substring(pos+1,
  -							     pair.length()));
  -		String values[];
  -		if (paramHashStringArray.containsKey(key)) {
  -		    String oldValues[] = (String[])paramHashStringArray.
  -			get(key);
  -		    values = new String[oldValues.length + 1];
  -		    for (int i = 0; i < oldValues.length; i++) {
  -			values[i] = oldValues[i];
  -		    }
  -		    values[oldValues.length] = value;
  -		} else {
  -		    values = new String[1];
  -		    values[0] = value;
  -		}
  -		paramHashStringArray.put(key, values);
  -	    } else {
  -		// we don't have a valid chunk of form data, ignore
  +    // incredibly inefficient data representation for parameters,
  +    // until we test the new one
  +    private void addParam( String key, String value ) {
  +	String values[];
  +	if (paramHashStringArray.containsKey(key)) {
  +	    String oldValues[] = (String[])paramHashStringArray.
  +		get(key);
  +	    values = new String[oldValues.length + 1];
  +	    for (int i = 0; i < oldValues.length; i++) {
  +		values[i] = oldValues[i];
   	    }
  -        }
  +	    values[oldValues.length] = value;
  +	} else {
  +	    values = new String[1];
  +	    values[0] = value;
  +	}
  +	
  +	
  +	paramHashStringArray.put(key, values);
  +    }
  +
  +    public void setURLDecoder( UDecoder u ) {
  +	urlDec=u;
       }
   
       // -------------------- Parameter parsing --------------------
   
       // This code is not used right now - it's the optimized version
  -    // of the above. 
  +    // of the above.
  +
  +    // we are called from a single thread - we can do it the hard way
  +    // if needed
  +    ByteChunk tmpName=new ByteChunk();
  +    ByteChunk tmpValue=new ByteChunk();
  +    CharChunk tmpNameC=new CharChunk(1024);
  +    CharChunk tmpValueC=new CharChunk(1024);
       
  -    /**
  -     * 
  -     */
       public void processParameters( byte bytes[], int start, int len ) {
   	int end=start+len;
   	int pos=start;
   	
  +	if( debug>0 ) 
  +	    log( "Bytes: " + new String( bytes, start, len ));
  +
           do {
   	    int nameStart=pos;
   	    int nameEnd=ByteChunk.indexOf(bytes, nameStart, end, '=' );
  @@ -376,12 +369,32 @@
   		// invalid chunk - it's better to ignore
   		// XXX log it ?
   	    }
  +	    tmpName.setBytes( bytes, nameStart, nameEnd-nameStart );
  +	    tmpValue.setBytes( bytes, valStart, valEnd-valStart );
  +	    tmpName.setEncoding( encoding );
  +	    tmpValue.setEncoding( encoding );
   	    
  -	    int field=this.addField();
  -	    this.getName( field ).setBytes( bytes,
  -					    nameStart, nameEnd );
  -	    this.getValue( field ).setBytes( bytes,
  -					     valStart, valEnd );
  +	    try {
  +		if( debug > 0 )
  +		    log( tmpName + "= " + tmpValue);
  +
  +		if( urlDec==null ) {
  +		    urlDec=new UDecoder();   
  +		}
  +		urlDec.convert( tmpName );
  +		urlDec.convert( tmpValue );
  +
  +		if( debug > 0 )
  +		    log( tmpName + "= " + tmpValue);
  +		
  +		addParam( tmpName.toString(), tmpValue.toString() );
  +	    } catch( IOException ex ) {
  +		ex.printStackTrace();
  +	    }
  +
  +	    tmpName.recycle();
  +	    tmpValue.recycle();
  +
   	} while( pos<end );
       }
   
  @@ -389,6 +402,8 @@
   	int end=start+len;
   	int pos=start;
   	
  +	if( debug>0 ) 
  +	    log( "Chars: " + new String( chars, start, len ));
           do {
   	    int nameStart=pos;
   	    int nameEnd=CharChunk.indexOf(chars, nameStart, end, '=' );
  @@ -405,17 +420,36 @@
   		// XXX log it ?
   	    }
   	    
  -	    int field=this.addField();
  -	    this.getName( field ).setChars( chars,
  -					    nameStart, nameEnd );
  -	    this.getValue( field ).setChars( chars,
  -					     valStart, valEnd );
  +	    try {
  +		tmpNameC.append( chars, nameStart, nameEnd-nameStart );
  +		tmpValueC.append( chars, valStart, valEnd-valStart );
  +
  +		if( debug > 0 )
  +		    log( tmpNameC + "= " + tmpValueC);
  +
  +		if( urlDec==null ) {
  +		    urlDec=new UDecoder();   
  +		}
  +
  +		urlDec.convert( tmpNameC );
  +		urlDec.convert( tmpValueC );
  +
  +		if( debug > 0 )
  +		    log( tmpNameC + "= " + tmpValueC);
  +		
  +		addParam( tmpNameC.toString(), tmpValueC.toString() );
  +	    } catch( IOException ex ) {
  +		ex.printStackTrace();
  +	    }
  +
  +	    tmpNameC.recycle();
  +	    tmpValueC.recycle();
  +
   	} while( pos<end );
       }
  -
       
       public void processParameters( MessageBytes data ) {
  -	if( data==null || data.getLength() <= 0 ) return;
  +	if( data==null || data.isNull() || data.getLength() <= 0 ) return;
   
   	if( data.getType() == MessageBytes.T_BYTES ) {
   	    ByteChunk bc=data.getByteChunk();
  @@ -430,6 +464,8 @@
   	}
       }
   
  +    /** Debug purpose
  +     */
       public String paramsAsString() {
   	StringBuffer sb=new StringBuffer();
   	Enumeration en= paramHashStringArray.keys();
  @@ -443,4 +479,66 @@
   	}
   	return sb.toString();
       }
  +
  +    private static int debug=1;
  +    private void log(String s ) {
  +	System.out.println("Parameters: " + s );
  +    }
  +   
  +    // -------------------- Old code, needs rewrite --------------------
  +    
  +    /** Used by RequestDispatcher
  +     */
  +    public void processParameters( String str ) {
  +	int end=str.length();
  +	int pos=0;
  +	if( debug > 0)
  +	    log("String: " + str );
  +	
  +        do {
  +	    int nameStart=pos;
  +	    int nameEnd=str.indexOf('=', nameStart );
  +	    if( nameEnd== -1 ) nameEnd=end;
  +
  +	    int valStart=nameEnd+1;
  +	    int valEnd=str.indexOf('&', valStart);
  +	    if( valEnd== -1 ) valEnd=end;
  +	    pos=valEnd+1;
  +	    
  +	    if( nameEnd<=nameStart ) {
  +		continue;
  +	    }
  +	    if( debug>0)
  +		log( "XXX " + nameStart + " " + nameEnd + " "
  +		     + valStart + " " + valEnd );
  +	    
  +	    try {
  +		tmpNameC.append(str, nameStart, nameEnd-nameStart );
  +		tmpValueC.append(str, valStart, valEnd-valStart );
  +	    
  +		if( debug > 0 )
  +		    log( tmpNameC + "= " + tmpValueC);
  +
  +		if( urlDec==null ) {
  +		    urlDec=new UDecoder();   
  +		}
  +
  +		urlDec.convert( tmpNameC );
  +		urlDec.convert( tmpValueC );
  +
  +		if( debug > 0 )
  +		    log( tmpNameC + "= " + tmpValueC);
  +		
  +		addParam( tmpNameC.toString(), tmpValueC.toString() );
  +	    } catch( IOException ex ) {
  +		ex.printStackTrace();
  +	    }
  +
  +	    tmpNameC.recycle();
  +	    tmpValueC.recycle();
  +
  +	} while( pos<end );
  +    }
  +
  +
   }