tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@locus.apache.org
Subject cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util/http AcceptLanguage.java ContentType.java HttpMessages.java Parameters.java
Date Sat, 30 Dec 2000 07:54:18 GMT
costin      00/12/29 23:54:18

  Modified:    src/facade22/org/apache/tomcat/facade CookieFacade.java
                        HttpServletRequestFacade.java
                        HttpServletResponseFacade.java
               src/share/org/apache/tomcat/core Request.java Response.java
               src/share/org/apache/tomcat/modules/server
                        Ajp12Interceptor.java Http10.java
                        Http10Interceptor.java JNIConnectionHandler.java
               src/share/org/apache/tomcat/request AccessInterceptor.java
                        SimpleMapper1.java StaticInterceptor.java
               src/share/org/apache/tomcat/util ByteChunk.java
                        CharChunk.java MessageBytes.java
               src/share/org/apache/tomcat/util/http Parameters.java
  Added:       src/share/org/apache/tomcat/util/http AcceptLanguage.java
                        ContentType.java HttpMessages.java
  Removed:     src/share/org/apache/tomcat/helper RequestUtil.java
  Log:
  RequestUtils - split into util.http.AcceptLanguage and ContentType ( tools
  for parsing the 2 headers ), HttpMessages for localized http codes.
  
  The chunk that parse dates is already in DateTools, the code for param.
  processing is moved to Parameters. Unescaping urls is in MessageBytes
  ( rewritten using Apache2.0 util.c model ).
  
  RequestUtils was created during refactoring - most complex code from core
  was moved in this super-class. The fact that it's now split by functionality
  doesn't make the code more efficient - it still need optimizations, but
  it'll be easier this way.
  
  Parameters is the largest chunk that I want to finish, plus Sessions ( sorry,
  I said I'll do the fix today - I'm very slow lately ).
  
  After this change we finally got the 3 separated components(core, apr, modules)
  
  Revision  Changes    Path
  1.5       +0 -1      jakarta-tomcat/src/facade22/org/apache/tomcat/facade/CookieFacade.java
  
  Index: CookieFacade.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/CookieFacade.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- CookieFacade.java	2000/11/30 22:43:46	1.4
  +++ CookieFacade.java	2000/12/30 07:54:10	1.5
  @@ -62,7 +62,6 @@
   
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.util.http.*;
  -import org.apache.tomcat.helper.RequestUtil;
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.facade.*;
   import java.io.*;
  
  
  
  1.15      +3 -3      jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpServletRequestFacade.java
  
  Index: HttpServletRequestFacade.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpServletRequestFacade.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- HttpServletRequestFacade.java	2000/12/29 21:24:32	1.14
  +++ HttpServletRequestFacade.java	2000/12/30 07:54:10	1.15
  @@ -62,7 +62,6 @@
   
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.util.http.*;
  -import org.apache.tomcat.helper.RequestUtil;
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.facade.*;
   import org.apache.tomcat.session.*;
  @@ -178,7 +177,7 @@
   	String value=request.getHeader( name );
   	if( value==null) return -1;
   	
  -	long date=RequestUtil.toDate(value);
  +	long date=DateTool.parseDate(value);
   	if( date==-1) {
   	    String msg = sm.getString("httpDate.pe", value);
   	    throw new IllegalArgumentException(msg);
  @@ -360,7 +359,8 @@
       /** Delegate to RequestUtil
        */
       public Enumeration getLocales() {
  -        return RequestUtil.getLocales(request.getMimeHeaders());
  +	MimeHeaders headers=request.getMimeHeaders();
  +        return AcceptLanguage.getLocales(headers.getHeader("Accept-Language"));
       }
   
       /** Delegate to Context
  
  
  
  1.15      +0 -1      jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpServletResponseFacade.java
  
  Index: HttpServletResponseFacade.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpServletResponseFacade.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- HttpServletResponseFacade.java	2000/12/26 22:50:47	1.14
  +++ HttpServletResponseFacade.java	2000/12/30 07:54:10	1.15
  @@ -63,7 +63,6 @@
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.util.http.*;
   import org.apache.tomcat.core.*;
  -import org.apache.tomcat.helper.*;
   import java.io.*;
   import java.net.*;
   import java.util.*;
  
  
  
  1.85      +33 -8     jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java
  
  Index: Request.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java,v
  retrieving revision 1.84
  retrieving revision 1.85
  diff -u -r1.84 -r1.85
  --- Request.java	2000/12/29 20:31:29	1.84
  +++ Request.java	2000/12/30 07:54:12	1.85
  @@ -65,8 +65,7 @@
   import org.apache.tomcat.util.SimplePrincipal;
   import org.apache.tomcat.util.MessageBytes;
   
  -// XXX 
  -import org.apache.tomcat.helper.RequestUtil;
  +import org.apache.tomcat.util.http.ContentType;
   
   import org.apache.tomcat.util.http.*;
   
  @@ -347,7 +346,7 @@
   
       public String getCharacterEncoding() {
           if(charEncoding!=null) return charEncoding;
  -        charEncoding = RequestUtil.getCharsetFromContentType( getContentType());
  +        charEncoding = ContentType.getCharsetFromContentType(getContentType());
   	return charEncoding;
       }
   
  @@ -704,16 +703,42 @@
   	    String qString=queryString().toString();
   	    if(qString!=null) {
   		didParameters=true;
  -		RequestUtil.processFormData( qString, parameters );
  +		Parameters.processFormData( qString, parameters );
   	    }
   	}
   	if (!didReadFormData) {
   	    didReadFormData = true;
  -	    Hashtable postParameters=RequestUtil.readFormData( this );
  -	    if(postParameters!=null)
  -		parameters = RequestUtil.mergeParameters(parameters,
  -							 postParameters);
  +	    int len=Parameters.formContentLength( getContentType(),
  +						  getContentLength());
  +	    if( len > 0 ) {
  +		// based on HttpUtils, very ,very slow and bad
  +		byte[] formData = new byte [contentLength];
  +		try {
  +		    readBody( formData, contentLength );
  +		} catch(IOException ex ) {
  +		    return;
  +		}
  +
  +		Hashtable postParameters=Parameters.processFormData(formData);
  +		parameters = Parameters.mergeParameters(parameters,
  +							postParameters);
  +	    }
   	}
  +    }
  +
  +    private int readBody(byte body[], int len)
  +	throws IOException
  +    {
  +	int offset = 0;
  +	
  +	do {
  +	    int inputLen = doRead(body, offset, len - offset);
  +	    if (inputLen <= 0) {
  +		return offset;
  +	    }
  +	    offset += inputLen;
  +	} while ((len - offset) > 0);
  +	return len;
       }
   
   
  
  
  
  1.46      +3 -3      jakarta-tomcat/src/share/org/apache/tomcat/core/Response.java
  
  Index: Response.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Response.java,v
  retrieving revision 1.45
  retrieving revision 1.46
  diff -u -r1.45 -r1.46
  --- Response.java	2000/12/29 20:31:29	1.45
  +++ Response.java	2000/12/30 07:54:12	1.46
  @@ -67,7 +67,7 @@
   import org.apache.tomcat.util.MimeHeaders;
   
   // XXX 
  -import org.apache.tomcat.helper.RequestUtil;
  +import org.apache.tomcat.util.http.ContentType;
   
   /**
    *
  @@ -424,7 +424,7 @@
   
           // Set the contentType for header output
           // Use the setContentType() method so encoding is set properly
  -        String newType = RequestUtil.constructLocalizedContentType(contentType,
  +        String newType = ContentType.constructLocalizedContentType(contentType,
   								   locale);
           setContentType(newType);
   
  @@ -439,7 +439,7 @@
       public void setContentType(String contentType) {
           if( included ) return;
   	this.contentType = contentType;
  -	String encoding = RequestUtil.getCharsetFromContentType(contentType);
  +	String encoding = ContentType.getCharsetFromContentType(contentType);
           if (encoding != null) {
   	    characterEncoding = encoding;
           }
  
  
  
  1.10      +2 -1      jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp12Interceptor.java
  
  Index: Ajp12Interceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp12Interceptor.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- Ajp12Interceptor.java	2000/12/29 19:59:19	1.9
  +++ Ajp12Interceptor.java	2000/12/30 07:54:14	1.10
  @@ -71,6 +71,7 @@
   import org.apache.tomcat.helper.*;
   import org.apache.tomcat.util.net.*;
   import org.apache.tomcat.util.*;
  +import org.apache.tomcat.util.http.*;
   
   /* 
    */
  @@ -260,7 +261,7 @@
   
       public void endHeaders()  throws IOException {
   	super.endHeaders();
  -	sendStatus( status, RequestUtil.getMessage( status ));
  +	sendStatus( status, HttpMessages.getMessage( status ));
   	http.sendHeaders( getMimeHeaders() );
       }
   
  
  
  
  1.5       +1 -4      jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Http10.java
  
  Index: Http10.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Http10.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Http10.java	2000/12/03 22:29:38	1.4
  +++ Http10.java	2000/12/30 07:54:14	1.5
  @@ -300,10 +300,7 @@
   	// Perform URL decoding only if necessary
   	if ((uriMB.indexOf('%') >= 0) || (uriMB.indexOf('+') >= 0)) {
   	    try {
  -		// XXX rewrite URLDecode to avoid allocation
  -		String requestURI = uriMB.toString();
  -		requestURI = RequestUtil.URLDecode(requestURI);
  -		uriMB.setString( requestURI );
  +		uriMB.unescapeURL();
   	    } catch (Exception e) {
   		return 400;
   	    }
  
  
  
  1.10      +2 -1      jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Http10Interceptor.java
  
  Index: Http10Interceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Http10Interceptor.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- Http10Interceptor.java	2000/12/17 02:37:35	1.9
  +++ Http10Interceptor.java	2000/12/30 07:54:14	1.10
  @@ -66,6 +66,7 @@
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.helper.*;
   import org.apache.tomcat.util.*;
  +import org.apache.tomcat.util.http.*;
   import org.apache.tomcat.util.net.*;
   import org.apache.tomcat.util.net.ServerSocketFactory;
   import org.apache.tomcat.util.log.*;
  @@ -307,7 +308,7 @@
   
       public void endHeaders()  throws IOException {
   	super.endHeaders();
  -	http.sendStatus( status, RequestUtil.getMessage( status ));
  +	http.sendStatus( status, HttpMessages.getMessage( status ));
   	http.sendHeaders( getMimeHeaders() );
       }
   
  
  
  
  1.6       +5 -4      jakarta-tomcat/src/share/org/apache/tomcat/modules/server/JNIConnectionHandler.java
  
  Index: JNIConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/JNIConnectionHandler.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- JNIConnectionHandler.java	2000/12/26 23:35:34	1.5
  +++ JNIConnectionHandler.java	2000/12/30 07:54:14	1.6
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/JNIConnectionHandler.java,v
1.5 2000/12/26 23:35:34 costin Exp $
  - * $Revision: 1.5 $
  - * $Date: 2000/12/26 23:35:34 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/JNIConnectionHandler.java,v
1.6 2000/12/30 07:54:14 costin Exp $
  + * $Revision: 1.6 $
  + * $Date: 2000/12/30 07:54:14 $
    *
    * ====================================================================
    *
  @@ -66,6 +66,7 @@
   import java.io.IOException;
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.util.*;
  +import org.apache.tomcat.util.http.*;
   import org.apache.tomcat.helper.*;
   import java.util.Vector;
   import java.io.File;
  @@ -408,7 +409,7 @@
           }
   
           if(h.startReasponse(s, l, status,
  -			    RequestUtil.getMessage(status),
  +			    HttpMessages.getMessage(status),
   			    headerNames, headerValues, hcnt) <= 0) {
               throw new IOException("JNI startReasponse implementation error");
           }
  
  
  
  1.31      +7 -2      jakarta-tomcat/src/share/org/apache/tomcat/request/AccessInterceptor.java
  
  Index: AccessInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/AccessInterceptor.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- AccessInterceptor.java	2000/12/28 01:15:38	1.30
  +++ AccessInterceptor.java	2000/12/30 07:54:15	1.31
  @@ -242,8 +242,13 @@
   	SecurityConstraints ctxSec=(SecurityConstraints)ctx.getContainer().
   	    getNote( secMapNote );
   	if( ctxSec==null || ctxSec.patterns==0 ) return 0; // fast exit
  -	
  -	String reqURI = RequestUtil.URLDecode(req.requestURI().toString());
  +
  +	MessageBytes reqURIMB=req.requestURI();
  +	if (reqURIMB.indexOf('%') >= 0 || reqURIMB.indexOf( '+' ) >= 0) {
  +	    log("Shouldn't happen - the request is decoded earlier");
  +	    reqURIMB.unescapeURL();
  +	}
  +	String reqURI = req.requestURI().toString();
   	String ctxPath= ctx.getPath();
   	String path=reqURI.substring( ctxPath.length());
   	String method=req.method().toString();
  
  
  
  1.29      +3 -1      jakarta-tomcat/src/share/org/apache/tomcat/request/SimpleMapper1.java
  
  Index: SimpleMapper1.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/SimpleMapper1.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- SimpleMapper1.java	2000/12/26 23:34:23	1.28
  +++ SimpleMapper1.java	2000/12/30 07:54:15	1.29
  @@ -252,7 +252,9 @@
   
   	if (pathMB.indexOf('%') >= 0 || pathMB.indexOf( '+' ) >= 0) {
   	    // XXX rewrite URLDecode to avoid allocation
  -	    pathMB.setString( RequestUtil.URLDecode(pathMB.toString()) );
  +	    log( "Found encoded char - it should have been decoded earlier");
  +	    pathMB.unescapeURL();
  +	    // pathMB.setString( RequestUtil.URLDecode(pathMB.toString()) );
   	}
   	try {
   	    //	    String host=null;
  
  
  
  1.30      +3 -2      jakarta-tomcat/src/share/org/apache/tomcat/request/StaticInterceptor.java
  
  Index: StaticInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/StaticInterceptor.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- StaticInterceptor.java	2000/12/29 21:24:34	1.29
  +++ StaticInterceptor.java	2000/12/30 07:54:15	1.30
  @@ -60,8 +60,8 @@
   
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.request.*;
  -import org.apache.tomcat.helper.*;
   import org.apache.tomcat.util.*;
  +import org.apache.tomcat.util.http.*;
   import java.io.*;
   import java.net.*;
   import java.text.*;
  @@ -355,7 +355,8 @@
       {
   	// this is how get locale is implemented. Ugly, but it's in
   	// the next round of optimizations
  -	Locale locale=RequestUtil.getLocale(req.getMimeHeaders());
  +	String acceptL=req.getMimeHeaders().getHeader( "Accept-Language");
  +	Locale locale=AcceptLanguage.getLocale(acceptL);;
   	StringManager sm=StringManager.
   	    getManager("org.apache.tomcat.resources",locale);
   	DateFormat dateFormat =
  
  
  
  1.3       +45 -0     jakarta-tomcat/src/share/org/apache/tomcat/util/ByteChunk.java
  
  Index: ByteChunk.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/ByteChunk.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ByteChunk.java	2000/12/26 23:35:37	1.2
  +++ ByteChunk.java	2000/12/30 07:54:16	1.3
  @@ -319,7 +319,51 @@
   	return true;
       }
   
  +    // based on ap_unescape_url ( util.c, Apache2.0 )
  +    public int unescapeURL()
  +    {
  +	int end=bytesOff+ bytesLen;
  +	int idx= indexOf( bytes, bytesOff, end, '%' );
  +	if( idx<0) return 0;
  +
  +	for( int j=idx; j<end; j++, idx++ ) {
  +	    if( bytes[ j ] != '%' ) {
  +		bytes[idx]=bytes[j];
  +	    } else {
  +		// read next 2 digits
  +		if( j+2 >= end ) {
  +		    // invalid
  +		    return 400; // BAD_REQUEST
  +		}
  +		byte b1= bytes[j+1];
  +		byte b2=bytes[j+2];
  +		if( !isHexDigit( b1 ) || ! isHexDigit(b2 ))
  +		    return 400;
  +		
  +		j+=2;
  +		int res=x2c( b1, b2 );
  +		if( res=='/' || res=='\0' )
  +		    return 400;
  +		bytes[idx]=(byte)res;
  +	    }
  +	}
  +	return 0;
  +    }
  +
  +    public static boolean isHexDigit( int c ) {
  +	return ( ( c>='0' && c<='9' ) ||
  +		 ( c>='a' && c<='f' ) ||
  +		 ( c>='A' && c<='F' ));
  +    }
       
  +    public static int x2c( byte b1, byte b2 ) {
  +	int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 :
  +	    (b1 -'0');
  +	digit*=16;
  +	digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 :
  +	    (b2 -'0');
  +	return digit;
  +    }
   
       // -------------------- Hash code  --------------------
   
  @@ -432,4 +476,5 @@
       }
   
   
  +    
   }
  
  
  
  1.3       +118 -0    jakarta-tomcat/src/share/org/apache/tomcat/util/CharChunk.java
  
  Index: CharChunk.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/CharChunk.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CharChunk.java	2000/12/26 23:35:37	1.2
  +++ CharChunk.java	2000/12/30 07:54:16	1.3
  @@ -288,6 +288,124 @@
   	return -1;
       }
   
  +    // based on ap_unescape_url ( util.c, Apache2.0 )
  +    public int unescapeURL()
  +    {
  +	int end=charsOff+ charsLen;
  +	int idx= indexOf( chars, charsOff, end, '%' );
  +	if( idx<0) return 0;
  +
  +	for( int j=idx; j<end; j++, idx++ ) {
  +	    if( chars[ j ] != '%' ) {
  +		chars[idx]=chars[j];
  +	    } else {
  +		// read next 2 digits
  +		if( j+2 >= end ) {
  +		    // invalid
  +		    return 400; // BAD_REQUEST
  +		}
  +		char b1= chars[j+1];
  +		char b2=chars[j+2];
  +		if( !isHexDigit( b1 ) || ! isHexDigit(b2 ))
  +		    return 400;
  +		
  +		j+=2;
  +		int res=x2c( b1, b2 );
  +		if( res=='/' || res=='\0' )
  +		    return 400;
  +		chars[idx]=(char)res;
  +	    }
  +	}
  +	return 0;
  +    }
  +
  +    public static boolean isHexDigit( int c ) {
  +	return ( ( c>='0' && c<='9' ) ||
  +		 ( c>='a' && c<='f' ) ||
  +		 ( c>='A' && c<='F' ));
  +    }
  +    
  +    public static int x2c( char b1, char b2 ) {
  +	int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 :
  +	    (b1 -'0');
  +	digit*=16;
  +	digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 :
  +	    (b2 -'0');
  +	return digit;
  +    }
  +
  +
  +    
  +    /**
  +     * This method decodes the given urlencoded string.
  +     *
  +     * @param  str the url-encoded string
  +     * @return the decoded string
  +     * @exception IllegalArgumentException If a '%' is not
  +     * followed by a valid 2-digit hex number.
  +     *
  +     * @author: cut & paste from JServ, much faster that previous tomcat impl 
  +     */
  +    public final static String unescapeURL(String str)
  +    {
  +	// old code
  +	System.out.println("XXX old unescape URL "+ str);
  +
  +        if (str == null)  return  null;
  +	
  +	// pay for what you use - unencoded requests will not get
  +	// less overhead
  +	// XXX this should be in the caller ?
  +	if( str.indexOf( '+' ) <0 && str.indexOf( '%' ) < 0 )
  +	    return str;
  +	
  +        StringBuffer dec = new StringBuffer();    // decoded string output
  +        int strPos = 0;
  +        int strLen = str.length();
  +
  +        dec.ensureCapacity(str.length());
  +        while (strPos < strLen) {
  +            int laPos;        // lookahead position
  +
  +            // look ahead to next URLencoded metacharacter, if any
  +            for (laPos = strPos; laPos < strLen; laPos++) {
  +                char laChar = str.charAt(laPos);
  +                if ((laChar == '+') || (laChar == '%')) {
  +                    break;
  +                }
  +            }
  +
  +            // if there were non-metacharacters, copy them all as a block
  +            if (laPos > strPos) {
  +                dec.append(str.substring(strPos,laPos));
  +                strPos = laPos;
  +            }
  +
  +            // shortcut out of here if we're at the end of the string
  +            if (strPos >= strLen) {
  +                break;
  +            }
  +
  +            // process next metacharacter
  +            char metaChar = str.charAt(strPos);
  +            if (metaChar == '+') {
  +                dec.append(' ');
  +                strPos++;
  +                continue;
  +            } else if (metaChar == '%') {
  +		// We throw the original exception - the super will deal with
  +		// it
  +		//                try {
  +		dec.append((char)Integer.
  +			   parseInt(str.substring(strPos + 1, strPos + 3),16));
  +                strPos += 3;
  +            }
  +        }
  +
  +        return dec.toString();
  +    }
  +
  +
   
   
   }
  
  
  
  1.15      +13 -0     jakarta-tomcat/src/share/org/apache/tomcat/util/MessageBytes.java
  
  Index: MessageBytes.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MessageBytes.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- MessageBytes.java	2000/12/07 18:34:51	1.14
  +++ MessageBytes.java	2000/12/30 07:54:16	1.15
  @@ -345,6 +345,19 @@
   	}
       }
   
  +    public int unescapeURL() {
  +	switch (type) {
  +	case T_STR:
  +	    if( strValue==null ) return 0;
  +	    strValue=CharChunk.unescapeURL( strValue );
  +	case T_CHARS:
  +	    return charC.unescapeURL();
  +	case T_BYTES:
  +	    return byteC.unescapeURL();
  +	}
  +	return 0;
  +    }
  +    
       public boolean equals(MessageBytes mb) {
   	switch (type) {
   	case T_STR:
  
  
  
  1.5       +154 -0    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.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Parameters.java	2000/12/26 23:35:38	1.4
  +++ Parameters.java	2000/12/30 07:54:18	1.5
  @@ -184,5 +184,159 @@
       public void mergeParameters( Parameters extra ) {
   	
       }
  +
  +
  +    // XXX Generic code moved from RequestUtil - will be replaced
  +    // with more efficient code.
  +        /** Combine 2 hashtables into a new one.
  +     *  XXX Will move to the MimeHeaders equivalent for params.
  +     */
  +    public static Hashtable mergeParameters(Hashtable one, Hashtable two) {
  +	// Try some shortcuts
  +	if (one.size() == 0) {
  +	    return two;
  +	}
  +
  +	if (two.size() == 0) {
  +	    return one;
  +	}
  +
  +	Hashtable combined = (Hashtable) one.clone();
  +
  +        Enumeration e = two.keys();
  +
  +	while (e.hasMoreElements()) {
  +	    String name = (String) e.nextElement();
  +	    String[] oneValue = (String[]) one.get(name);
  +	    String[] twoValue = (String[]) two.get(name);
  +	    String[] combinedValue;
  +
  +	    if (oneValue == null) {
  +		combinedValue = twoValue;
  +	    }
  +
  +	    else {
  +		combinedValue = new String[oneValue.length + twoValue.length];
  +
  +	        System.arraycopy(oneValue, 0, combinedValue, 0,
  +                    oneValue.length);
  +	        System.arraycopy(twoValue, 0, combinedValue,
  +                    oneValue.length, twoValue.length);
  +	    }
  +
  +	    combined.put(name, combinedValue);
  +	}
  +
  +	return combined;
  +    }
  +    
  +    public static void processFormData(String data, Hashtable parameters) {
  +        // XXX
  +        // 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 = unUrlDecode(pair.substring(0, pos));
  +		String value = unUrlDecode(pair.substring(pos+1,
  +							  pair.length()));
  +		String values[];
  +		if (parameters.containsKey(key)) {
  +		    String oldValues[] = (String[])parameters.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;
  +		}
  +		parameters.put(key, values);
  +	    } else {
  +		// we don't have a valid chunk of form data, ignore
  +	    }
  +        }
  +    }
  +
  +    // from RequestUtil
  +    public static Hashtable processFormData(byte data[]   ) {
  +	Hashtable postParameters =  new Hashtable();
  +
  +	try {
  +	    String postedBody = new String(data, 0, data.length,
  +					   "8859_1");
  +	    
  +	    Parameters.processFormData( postedBody, postParameters);
  +	    return postParameters;
  +	} catch( UnsupportedEncodingException ex ) {
  +	    return postParameters;
  +	}
  +    }
  +
  +    /** Decode a URL-encoded string. Inefficient.
  +     */
  +    private static String unUrlDecode(String data) {
  +	System.out.println("DECODING : " +data );
  +	StringBuffer buf = new StringBuffer();
  +	for (int i = 0; i < data.length(); i++) {
  +	    char c = data.charAt(i);
  +	    switch (c) {
  +	    case '+':
  +		buf.append(' ');
  +		break;
  +	    case '%':
  +		// XXX XXX 
  +		try {
  +		    buf.append((char) Integer.parseInt(data.substring(i+1,
  +                        i+3), 16));
  +		    i += 2;
  +		} catch (NumberFormatException e) {
  +                    String msg = "Decode error ";
  +		    // XXX no need to add sm just for that
  +		    // sm.getString("serverRequest.urlDecode.nfe", data);
  +
  +		    throw new IllegalArgumentException(msg);
  +		} catch (StringIndexOutOfBoundsException e) {
  +		    String rest  = data.substring(i);
  +		    buf.append(rest);
  +		    if (rest.length()==2)
  +			i++;
  +		}
  +		
  +		break;
  +	    default:
  +		buf.append(c);
  +		break;
  +	    }
  +	}
  +	return buf.toString();
  +    }           
  +
  +    // XXX Ugly, most be rewritten
  +    /** Process the POST data from a request.
  +     */
  +    public static int formContentLength( String contentType,
  +					 int contentLength )
  +    {
  +
  +	if (contentType != null) {
  +            if (contentType.indexOf(";")>0)
  +                contentType=contentType.substring(0,contentType.indexOf(";"));
  +            contentType = contentType.toLowerCase().trim();
  +        }
  +
  +	if (contentType != null &&
  +            contentType.startsWith("application/x-www-form-urlencoded")) {
  +	    
  +	    if( contentLength >0 ) return contentLength;
  +	}
  +	return 0;
  +    }
  +
  +    
  +
       
   }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/util/http/AcceptLanguage.java
  
  Index: AcceptLanguage.java
  ===================================================================
  /*
   * ====================================================================
   *
   * 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.tomcat.util.http;
  
  import org.apache.tomcat.util.*;
  
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import java.text.*;
  
  /**
   * 
   * 
   * @author James Duncan Davidson [duncan@eng.sun.com]
   * @author James Todd [gonzo@eng.sun.com]
   * @author Jason Hunter [jch@eng.sun.com]
   * @author Harish Prabandham
   * @author costin@eng.sun.com
   */
  public class AcceptLanguage {
      protected static StringManager sm =
          StringManager.getManager("org.apache.tomcat.resources");
      
      public static Locale getLocale(String acceptLanguage) {
  	if( acceptLanguage == null ) return Locale.getDefault();
  
          Hashtable languages = new Hashtable();
          Vector quality=new Vector();
          processAcceptLanguage(acceptLanguage, languages,quality);
  
          if (languages.size() == 0) return Locale.getDefault();
  
          Vector l = new Vector();
          extractLocales( languages,quality, l);
  
          return (Locale)l.elementAt(0);
      }
  
      public static Enumeration getLocales(String acceptLanguage) {
      	// Short circuit with an empty enumeration if null header
          if (acceptLanguage == null) {
              Vector v = new Vector();
              v.addElement(Locale.getDefault());
              return v.elements();
          }
  	
          Hashtable languages = new Hashtable();
          Vector quality=new Vector();
      	processAcceptLanguage(acceptLanguage, languages , quality);
  
          if (languages.size() == 0) {
              Vector v = new Vector();
              v.addElement(Locale.getDefault());
              return v.elements();
          }
      	Vector l = new Vector();
      	extractLocales( languages, quality , l);
      	return l.elements();
      }
  
      private static void processAcceptLanguage( String acceptLanguage,
  					      Hashtable languages, Vector q)
      {
          StringTokenizer languageTokenizer =
              new StringTokenizer(acceptLanguage, ",");
  
          while (languageTokenizer.hasMoreTokens()) {
              String language = languageTokenizer.nextToken().trim();
              int qValueIndex = language.indexOf(';');
              int qIndex = language.indexOf('q');
              int equalIndex = language.indexOf('=');
              Double qValue = new Double(1);
  
              if (qValueIndex > -1 &&
                      qValueIndex < qIndex &&
                      qIndex < equalIndex) {
      	        String qValueStr = language.substring(qValueIndex + 1);
                  language = language.substring(0, qValueIndex);
                  qValueStr = qValueStr.trim().toLowerCase();
                  qValueIndex = qValueStr.indexOf('=');
                  qValue = new Double(0);
                  if (qValueStr.startsWith("q") &&
                      qValueIndex > -1) {
                      qValueStr = qValueStr.substring(qValueIndex + 1);
                      try {
                          qValue = new Double(qValueStr.trim());
                      } catch (NumberFormatException nfe) {
                      }
                  }
              }
  
              // XXX
              // may need to handle "*" at some point in time
  
              if (! language.equals("*")) {
                  String key = qValue.toString();
                  Vector v;
                  if (languages.containsKey(key)) {
                      v = (Vector)languages.get(key) ;
                  } else {
                      v= new Vector();
                      q.addElement(qValue);
                  }
                  v.addElement(language);
                  languages.put(key, v);
              }
          }
      }
  
      private static void extractLocales(Hashtable languages, Vector q,Vector l)
      {
          // XXX We will need to order by q value Vector in the Future ?
          Enumeration e = q.elements();
          while (e.hasMoreElements()) {
              Vector v =
                  (Vector)languages.get(((Double)e.nextElement()).toString());
              Enumeration le = v.elements();
              while (le.hasMoreElements()) {
      	        String language = (String)le.nextElement();
  	        	String country = "";
          		int countryIndex = language.indexOf("-");
                  if (countryIndex > -1) {
                      country = language.substring(countryIndex + 1).trim();
                      language = language.substring(0, countryIndex).trim();
                  }
                  l.addElement(new Locale(language, country));
              }
          }
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/util/http/ContentType.java
  
  Index: ContentType.java
  ===================================================================
  /*
   * ====================================================================
   *
   * 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.tomcat.util.http;
  
  import org.apache.tomcat.util.*;
  
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import java.text.*;
  
  /**
   * Usefull methods for Content-Type processing
   * 
   * @author James Duncan Davidson [duncan@eng.sun.com]
   * @author James Todd [gonzo@eng.sun.com]
   * @author Jason Hunter [jch@eng.sun.com]
   * @author Harish Prabandham
   * @author costin@eng.sun.com
   */
  public class ContentType {
      protected static StringManager sm =
          StringManager.getManager("org.apache.tomcat.resources");
  	
  
      // Basically return everything after ";charset="
      // If no charset specified, use the HTTP default (ASCII) character set.
      public static String getCharsetFromContentType(String type) {
          if (type == null) {
              return null;
          }
          int semi = type.indexOf(";");
          if (semi == -1) {
              return null;
          }
          String afterSemi = type.substring(semi + 1);
          int charsetLocation = afterSemi.indexOf("charset=");
          if (charsetLocation == -1) {
              return null;
          }
          String afterCharset = afterSemi.substring(charsetLocation + 8);
          String encoding = afterCharset.trim();
          return encoding;
      }
  
      /** Utility method for parsing the mime type and setting
       *  the encoding to locale. Also, convert from java Locale to mime
       * encodings
       */
      public static String constructLocalizedContentType(String type,
  							Locale loc) {
          // Cut off everything after the semicolon
          int semi = type.indexOf(";");
          if (semi != -1) {
              type = type.substring(0, semi);
          }
  
          // Append the appropriate charset, based on the locale
          String charset = LocaleToCharsetMap.getCharset(loc);
          if (charset != null) {
              type = type + "; charset=" + charset;
          }
  
          return type;
      }
  
  }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/util/http/HttpMessages.java
  
  Index: HttpMessages.java
  ===================================================================
  /*
   * ====================================================================
   *
   * 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.tomcat.util.http;
  
  import org.apache.tomcat.util.StringManager;
  
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import java.text.*;
  
  /**
   * Handle (internationalized) HTTP messages.
   * 
   * @author James Duncan Davidson [duncan@eng.sun.com]
   * @author James Todd [gonzo@eng.sun.com]
   * @author Jason Hunter [jch@eng.sun.com]
   * @author Harish Prabandham
   * @author costin@eng.sun.com
   */
  public class HttpMessages {
      // XXX move message resources in this package
      protected static StringManager sm =
          StringManager.getManager("org.apache.tomcat.resources");
  	
      static String st_200=null;
      static String st_302=null;
      static String st_400=null;
      static String st_404=null;
      
      /** Get the status string associated with a status code.
       *  No I18N - return the messages defined in the HTTP spec.
       *  ( the user isn't supposed to see them, this is the last
       *  thing to translate)
       *
       *  Common messages are cached.
       *
       */
      public static String getMessage( int status ) {
  	// method from Response.
  	
  	// Does HTTP requires/allow international messages or
  	// are pre-defined? The user doesn't see them most of the time
  	switch( status ) {
  	case 200:
  	    if( st_200==null ) st_200=sm.getString( "sc.200");
  	    return st_200;
  	case 302:
  	    if( st_302==null ) st_302=sm.getString( "sc.302");
  	    return st_302;
  	case 400:
  	    if( st_400==null ) st_400=sm.getString( "sc.400");
  	    return st_400;
  	case 404:
  	    if( st_404==null ) st_404=sm.getString( "sc.404");
  	    return st_404;
  	}
  	return sm.getString("sc."+ status);
      }
  }
  
  
  

Mime
View raw message