📄 cookies.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomcat.util.http;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.StringTokenizer;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
/**
* 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 {
private static org.apache.juli.logging.Log log=
org.apache.juli.logging.LogFactory.getLog(Cookies.class );
// 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() ) {
pos++;
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==',' || pos>=end ) {
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -