⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cookies.java

📁 Tomcat 4.1与WebServer集成组件的源代码包.
💻 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.buf.MessageBytes;import org.apache.tomcat.util.buf.CharChunk;import org.apache.tomcat.util.buf.ByteChunk;import java.io.*;import java.util.*;import java.text.*;/** * A collection of cookies - reusable and tuned for server side performance. * Based on RFC2965 ( and 2109 ) * * This class is not synchronized. * * @author Costin Manolache * @author kevin seguin */public final class Cookies { // extends MultiMap {    // expected average number of cookies per request    public static final int INITIAL_SIZE=4;     ServerCookie scookies[]=new ServerCookie[INITIAL_SIZE];    int cookieCount=0;    boolean unprocessed=true;    MimeHeaders headers;        /**     *  Construct a new cookie collection, that will extract     *  the information from headers.     *     * @param headers Cookies are lazy-evaluated and will extract the     *     information from the provided headers.     */    public Cookies(MimeHeaders headers) {	this.headers=headers;    }    /**     * Construct a new uninitialized cookie collection.     * Use {@link #setHeaders} to initialize.     */    // [seguin] added so that an empty Cookies object could be    // created, have headers set, then recycled.    public Cookies() {    }    /**     * Set the headers from which cookies will be pulled.     * This has the side effect of recycling the object.     *     * @param headers Cookies are lazy-evaluated and will extract the     *     information from the provided headers.     */    // [seguin] added so that an empty Cookies object could be    // created, have headers set, then recycled.    public void setHeaders(MimeHeaders headers) {        recycle();        this.headers=headers;    }    /**     * Recycle.     */    public void recycle() {    	for( int i=0; i< cookieCount; i++ ) {	    if( scookies[i]!=null )		scookies[i].recycle();	}	cookieCount=0;	unprocessed=true;    }    /**     * EXPENSIVE!!!  only for debugging.     */    public String toString() {        StringWriter sw = new StringWriter();        PrintWriter pw = new PrintWriter(sw);        pw.println("=== Cookies ===");        int count = getCookieCount();        for (int i = 0; i < count; ++i) {            pw.println(getCookie(i).toString());        }        return sw.toString();    }    // -------------------- Indexed access --------------------        public ServerCookie getCookie( int idx ) {	if( unprocessed ) {	    getCookieCount(); // will also update the cookies	}	return scookies[idx];    }    public int getCookieCount() {	if( unprocessed ) {	    unprocessed=false;	    processCookies(headers);	}	return cookieCount;    }    // -------------------- Adding cookies --------------------    /** Register a new, unitialized cookie. Cookies are recycled, and     *  most of the time an existing ServerCookie object is returned.     *  The caller can set the name/value and attributes for the cookie     */    public ServerCookie addCookie() {	if( cookieCount >= scookies.length  ) {	    ServerCookie scookiesTmp[]=new ServerCookie[2*cookieCount];	    System.arraycopy( scookies, 0, scookiesTmp, 0, cookieCount);	    scookies=scookiesTmp;	}		ServerCookie c = scookies[cookieCount];	if( c==null ) {	    c= new ServerCookie();	    scookies[cookieCount]=c;	}	cookieCount++;	return c;    }    // code from CookieTools     /** Add all Cookie found in the headers of a request.     */    public  void processCookies( MimeHeaders headers ) {	if( headers==null )	    return;// nothing to process	// process each "cookie" header	int pos=0;	while( pos>=0 ) {	    // Cookie2: version ? not needed	    pos=headers.findHeader( "Cookie", pos );	    // no more cookie headers headers	    if( pos<0 ) break;	    MessageBytes cookieValue=headers.getValue( pos );	    if( cookieValue==null || cookieValue.isNull() ) continue;	    // Uncomment to test the new parsing code	    if( cookieValue.getType() == MessageBytes.T_BYTES ) {		if( dbg>0 ) log( "Parsing b[]: " + cookieValue.toString());		ByteChunk bc=cookieValue.getByteChunk();		processCookieHeader( bc.getBytes(),				     bc.getOffset(),				     bc.getLength());	    } else {		if( dbg>0 ) log( "Parsing S: " + cookieValue.toString());		processCookieHeader( cookieValue.toString() );	    }	    pos++;// search from the next position	}    }    /** Process a byte[] header - allowing fast processing of the     *  raw data     */    void processCookieHeader(  byte bytes[], int off, int len )    {	if( len<=0 || bytes==null ) return;	int end=off+len;	int pos=off;		int version=0; //sticky	ServerCookie sc=null;		while( pos<end ) {	    byte cc;	    // [ skip_spaces name skip_spaces "=" skip_spaces value EXTRA ; ] *	    if( dbg>0 ) log( "Start: " + pos + " " + end );	    	    pos=skipSpaces(bytes, pos, end);	    if( pos>=end )		return; // only spaces	    int startName=pos;	    if( dbg>0 ) log( "SN: " + pos );	    	    // Version should be the first token	    boolean isSpecial=false;	    if(bytes[pos]=='$') { pos++; isSpecial=true; }	    pos= findDelim1( bytes, startName, end); // " =;,"	    int endName=pos;	    // current = "=" or " " or DELIM	    pos= skipSpaces( bytes, endName, end ); 	    if( dbg>0 ) log( "DELIM: " + endName + " " + (char)bytes[pos]);	    if(pos >= end ) {		// it's a name-only cookie ( valid in RFC2109 )		if( ! isSpecial ) {		    sc=addCookie();		    sc.getName().setBytes( bytes, startName,					   endName-startName );		    sc.getValue().setString("");		    sc.setVersion( version );		    if( dbg>0 ) log( "Name only, end: " + startName + " " +				     endName);		}		return;	    }	    cc=bytes[pos];	    pos++;	    if( cc==';' || cc==',' ) {		if( ! isSpecial && startName!= endName ) {		    sc=addCookie();		    sc.getName().setBytes( bytes, startName,					   endName-startName );		    sc.getValue().setString("");		    sc.setVersion( version );		    if( dbg>0 ) log( "Name only: " + startName + " " + endName);		}		continue;	    }	    	    // we should have "=" ( tested all other alternatives )	    int startValue=skipSpaces( bytes, pos, end);	    int endValue=startValue;	    	    // quote is valid only in version=1 cookies	    cc=bytes[pos];	    if( version==1 && ( cc== '\'' || cc=='"' ) ) {		startValue++;		endValue=indexOf( bytes, startValue, end, cc );		pos=endValue+1; // to skip to next cookie 	    } else {		endValue=findDelim2( bytes, startValue, end );		pos=endValue+1;	    }	    	    // if not $Version, etc	    if( ! isSpecial ) {		sc=addCookie();		sc.getName().setBytes( bytes, startName, endName-startName );		sc.getValue().setBytes( bytes, startValue, endValue-startValue);		sc.setVersion( version );		if( dbg>0 ) log( "New: " + sc.getName() + "X=X" + sc.getValue());		continue;	    }	    	    // special - Path, Version, Domain, Port	    if( dbg>0 ) log( "Special: " + startName + " " + endName);	    // XXX TODO	    if( equals( "$Version", bytes, startName, endName ) ) {		if(dbg>0 ) log( "Found version " );		if( bytes[startValue]=='1' && endValue==startValue+1 ) {		    version=1;		    if(dbg>0 ) log( "Found version=1" );		}		continue;	    }	    if( sc==null ) {		// Path, etc without a previous cookie		continue;	    }	    if( equals( "$Path", bytes, startName, endName ) ) {                sc.getPath().setBytes( bytes, startValue, endValue-startValue );	    }	    if( equals( "$Domain", bytes, startName, endName ) ) {                sc.getDomain().setBytes( bytes, startValue, endValue-startValue );	    }	    if( equals( "$Port", bytes, startName, endName ) ) {                // sc.getPort().setBytes( bytes, startValue, endValue-startValue );	    }	}    }    // -------------------- Utils --------------------    public static int skipSpaces(  byte bytes[], int off, int end ) {	while( off < end ) {	    byte b=bytes[off];	    if( b!= ' ' ) return off;	    off ++;	}	return off;    }    public static int findDelim1( byte bytes[], int off, int end )    {	while( off < end ) {	    byte b=bytes[off];	    if( b==' ' || b=='=' || b==';' || b==',' )		return off;	    off++;	}	return off;    }    public static int findDelim2( byte bytes[], int off, int end )    {	while( off < end ) {	    byte b=bytes[off];	    if( b==';' || b==',' )		return off;	    off++;	}	return off;    }    public static int indexOf( byte bytes[], int off, int end, byte qq )    {	while( off < end ) {	    byte b=bytes[off];	    if( b==qq )		return off;	    off++;	}	return off;    }    public static int indexOf( byte bytes[], int off, int end, char qq )    {	while( off < end ) {	    byte b=bytes[off];	    if( b==qq )		return off;	    off++;	}	return off;    }        // XXX will be refactored soon!    public static boolean equals( String s, byte b[], int start, int end) {	int blen = end-start;	if (b == null || blen != s.length()) {	    return false;	}	int boff = start;	for (int i = 0; i < blen; i++) {	    if (b[boff++] != s.charAt(i)) {		return false;	    }	}	return true;    }        // ---------------------------------------------------------    // -------------------- DEPRECATED, OLD --------------------        private void processCookieHeader(  String cookieString )    {	if( dbg>0 ) log( "Parsing cookie header " + cookieString );	// normal cookie, with a string value.	// This is the original code, un-optimized - it shouldn't	// happen in normal case	StringTokenizer tok = new StringTokenizer(cookieString,						  ";", false);	while (tok.hasMoreTokens()) {	    String token = tok.nextToken();	    int i = token.indexOf("=");	    if (i > -1) {				// XXX		// the trims here are a *hack* -- this should		// be more properly fixed to be spec compliant				String name = token.substring(0, i).trim();		String value = token.substring(i+1, token.length()).trim();		// RFC 2109 and bug 		value=stripQuote( value );		ServerCookie cookie = addCookie();				cookie.getName().setString(name);		cookie.getValue().setString(value);		if( dbg > 0 ) log( "Add cookie " + name + "=" + value);	    } else {		// we have a bad cookie.... just let it go	    }	}    }    /**     *     * Strips quotes from the start and end of the cookie string     * This conforms to RFC 2109     *      * @param value            a <code>String</code> specifying the cookie      *                         value (possibly quoted).     *     * @see #setValue     *     */    private static String stripQuote( String value )    {	//	log("Strip quote from " + value );	if (((value.startsWith("\"")) && (value.endsWith("\""))) ||	    ((value.startsWith("'") && (value.endsWith("'"))))) {	    try {		return value.substring(1,value.length()-1);	    } catch (Exception ex) { 	    }	}	return value;    }      // log    static final int dbg=0;    public void log(String s ) {	System.out.println("Cookies: " + s);    }    /*    public static void main( String args[] ) {	test("foo=bar; a=b");	test("foo=bar;a=b");	test("foo=bar;a=b;");	test("foo=bar;a=b; ");	test("foo=bar;a=b; ;");	test("foo=;a=b; ;");	test("foo;a=b; ;");	// v1 	test("$Version=1; foo=bar;a=b");	test("$Version=1;foo=bar;a=b; ; ");	test("$Version=1;foo=;a=b; ; ");	test("$Version=1;foo= ;a=b; ; ");	test("$Version=1;foo;a=b; ; ");	test("$Version=1;foo=\"bar\";a=b; ; ");	test("$Version=1;foo=\"bar\";$Path=/examples;a=b; ; ");	test("$Version=1;foo=\"bar\";$Domain=apache.org;a=b");	test("$Version=1;foo=\"bar\";$Domain=apache.org;a=b;$Domain=yahoo.com");	// rfc2965	test("$Version=1;foo=\"bar\";$Domain=apache.org;$Port=8080;a=b");	// wrong	test("$Version=1;foo=\"bar\";$Domain=apache.org;$Port=8080;a=b");    }    public static void test( String s ) {	System.out.println("Processing " + s );	Cookies cs=new Cookies(null);	cs.processCookieHeader( s.getBytes(), 0, s.length());	for( int i=0; i< cs.getCookieCount() ; i++ ) {	    System.out.println("Cookie: " + cs.getCookie( i ));	}	        }    */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -