Added: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ServerCookie.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ServerCookie.java?rev=884412&view=auto
==============================================================================
--- 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ServerCookie.java
 (added)
+++ 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ServerCookie.java
 Thu Nov 26 06:41:00 2009
@@ -0,0 +1,819 @@
+/*
+ *  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.lite.http;
+
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.io.CBuffer;
+
+
+/**
+ *  Server-side cookie representation.
+ *  Allows recycling and uses MessageBytes as low-level
+ *  representation ( and thus the byte-> char conversion can be delayed
+ *  until we know the charset ).
+ *
+ *  Tomcat.core uses this recyclable object to represent cookies,
+ *  and the facade will convert it to the external representation.
+ */
+public class ServerCookie implements Serializable {
+    
+    // Version 0 (Netscape) attributes
+    private BBuffer name = BBuffer.allocate();
+    private BBuffer value = BBuffer.allocate();
+    
+    private CBuffer nameC = CBuffer.newInstance();
+
+    // Expires - Not stored explicitly. Generated from Max-Age (see V1)
+    private BBuffer path = BBuffer.allocate();
+    private BBuffer domain = BBuffer.allocate();
+    private boolean secure;
+    
+    // Version 1 (RFC2109) attributes
+    private BBuffer comment = BBuffer.allocate();
+    private int maxAge = -1;
+    private int version = 0;
+
+    // Other fields
+    private static final String OLD_COOKIE_PATTERN =
+        "EEE, dd-MMM-yyyy HH:mm:ss z";
+    private static final ThreadLocal<DateFormat> OLD_COOKIE_FORMAT =
+        new ThreadLocal<DateFormat>() {
+        protected DateFormat initialValue() {
+            DateFormat df =
+                new SimpleDateFormat(OLD_COOKIE_PATTERN, Locale.US);
+            df.setTimeZone(TimeZone.getTimeZone("GMT"));
+            return df;
+        }
+    };
+    
+    private static final String ancientDate;
+
+
+    static {
+        ancientDate = OLD_COOKIE_FORMAT.get().format(new Date(10000));
+    }
+
+    /**
+     * If set to true, we parse cookies according to the servlet spec,
+     */
+    public static final boolean STRICT_SERVLET_COMPLIANCE =
+        
Boolean.valueOf(System.getProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE",
 "false")).booleanValue();
+
+    /**
+     * If set to false, we don't use the IE6/7 Max-Age/Expires work around
+     */
+    public static final boolean ALWAYS_ADD_EXPIRES =
+        
Boolean.valueOf(System.getProperty("org.apache.tomcat.util.http.ServerCookie.ALWAYS_ADD_EXPIRES",
 "true")).booleanValue();
+
+    // Note: Servlet Spec =< 2.5 only refers to Netscape and RFC2109,
+    // not RFC2965
+
+    // Version 1 (RFC2965) attributes
+    // TODO Add support for CommentURL
+    // Discard - implied by maxAge <0
+    // TODO Add support for Port
+
+    public ServerCookie() {
+    }
+
+    public void recycle() {        
+        path.recycle();
+        name.recycle();
+        value.recycle();
+        comment.recycle();
+        maxAge=-1;
+        path.recycle();
+        domain.recycle();
+        version=0;
+        secure=false;
+    }
+
+    public BBuffer getComment() {
+        return comment;
+    }
+
+    public BBuffer getDomain() {
+        return domain;
+    }
+
+    public void setMaxAge(int expiry) {
+        maxAge = expiry;
+    }
+
+    public int getMaxAge() {
+        return maxAge;
+    }
+
+    public BBuffer getPath() {
+        return path;
+    }
+
+    public void setSecure(boolean flag) {
+        secure = flag;
+    }
+
+    public boolean getSecure() {
+        return secure;
+    }
+
+    public BBuffer getName() {
+        return name;
+    }
+
+    public BBuffer getValue() {
+        return value;
+    }
+
+    public int getVersion() {
+        return version;
+    }
+
+    public void setVersion(int v) {
+        version = v;
+    }
+
+
+    // -------------------- utils --------------------
+
+    public String toString() {
+        return "Cookie " + getName() + "=" + getValue() + " ; "
+            + getVersion() + " " + getPath() + " " + getDomain();
+    }
+    
+    private static final String tspecials = ",; ";
+    private static final String tspecials2 = "()<>@,;:\\\"/[]?={} \t";
+    private static final String tspecials2NoSlash = "()<>@,;:\\\"[]?={} \t";
+
+    /*
+     * Tests a string and returns true if the string counts as a
+     * reserved token in the Java language.
+     *
+     * @param value the <code>String</code> to be tested
+     *
+     * @return      <code>true</code> if the <code>String</code> is a reserved
+     *              token; <code>false</code> if it is not
+     */
+    public static boolean isToken(String value) {
+        return isToken(value,null);
+    }
+    
+    public static boolean isToken(String value, String literals) {
+        String tspecials = (literals==null?ServerCookie.tspecials:literals);
+        if( value==null) return true;
+        int len = value.length();
+
+        for (int i = 0; i < len; i++) {
+            char c = value.charAt(i);
+
+            if (tspecials.indexOf(c) != -1)
+                return false;
+        }
+        return true;
+    }
+
+    public static boolean containsCTL(String value, int version) {
+        if( value==null) return false;
+        int len = value.length();
+        for (int i = 0; i < len; i++) {
+            char c = value.charAt(i);
+            if (c < 0x20 || c >= 0x7f) {
+                if (c == 0x09)
+                    continue; //allow horizontal tabs
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean isToken2(String value) {
+        return isToken2(value,null);
+    }
+
+    public static boolean isToken2(String value, String literals) {
+        String tspecials2 = (literals==null?ServerCookie.tspecials2:literals);
+        if( value==null) return true;
+        int len = value.length();
+
+        for (int i = 0; i < len; i++) {
+            char c = value.charAt(i);
+            if (tspecials2.indexOf(c) != -1)
+                return false;
+        }
+        return true;
+    }
+
+    // -------------------- Cookie parsing tools
+
+    
+    /**
+     * Return the header name to set the cookie, based on cookie version.
+     */
+    public String getCookieHeaderName() {
+        return getCookieHeaderName(version);
+    }
+
+    /**
+     * Return the header name to set the cookie, based on cookie version.
+     */
+    public static String getCookieHeaderName(int version) {
+        // TODO Re-enable logging when RFC2965 is implemented
+        // log( (version==1) ? "Set-Cookie2" : "Set-Cookie");
+        if (version == 1) {
+            // XXX RFC2965 not referenced in Servlet Spec
+            // Set-Cookie2 is not supported by Netscape 4, 6, IE 3, 5
+            // Set-Cookie2 is supported by Lynx and Opera
+            // Need to check on later IE and FF releases but for now... 
+            // RFC2109
+            return "Set-Cookie";
+            // return "Set-Cookie2";
+        } else {
+            // Old Netscape
+            return "Set-Cookie";
+        }
+    }
+
+    // TODO RFC2965 fields also need to be passed
+    public static void appendCookieValue( StringBuffer headerBuf,
+                                          int version,
+                                          String name,
+                                          String value,
+                                          String path,
+                                          String domain,
+                                          String comment,
+                                          int maxAge,
+                                          boolean isSecure,
+                                          boolean isHttpOnly)
+    {
+        StringBuffer buf = new StringBuffer();
+        // Servlet implementation checks name
+        buf.append( name );
+        buf.append("=");
+        // Servlet implementation does not check anything else
+        
+        version = maybeQuote2(version, buf, value,true);
+
+        // Add version 1 specific information
+        if (version == 1) {
+            // Version=1 ... required
+            buf.append ("; Version=1");
+
+            // Comment=comment
+            if ( comment!=null ) {
+                buf.append ("; Comment=");
+                maybeQuote2(version, buf, comment);
+            }
+        }
+        
+        // Add domain information, if present
+        if (domain!=null) {
+            buf.append("; Domain=");
+            maybeQuote2(version, buf, domain);
+        }
+
+        // Max-Age=secs ... or use old "Expires" format
+        // TODO RFC2965 Discard
+        if (maxAge >= 0) {
+            if (version > 0) {
+                buf.append ("; Max-Age=");
+                buf.append (maxAge);
+            }
+            // IE6, IE7 and possibly other browsers don't understand Max-Age.
+            // They do understand Expires, even with V1 cookies!
+            if (version == 0 || ALWAYS_ADD_EXPIRES) {
+                // Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format )
+                buf.append ("; Expires=");
+                // To expire immediately we need to set the time in past
+                if (maxAge == 0)
+                    buf.append( ancientDate );
+                else
+                    OLD_COOKIE_FORMAT.get().format(
+                            new Date(System.currentTimeMillis() +
+                                    maxAge*1000L),
+                            buf, new FieldPosition(0));
+            }
+        }
+
+        // Path=path
+        if (path!=null) {
+            buf.append ("; Path=");
+            if (version==0) {
+                maybeQuote2(version, buf, path);
+            } else {
+                maybeQuote2(version, buf, path, 
ServerCookie.tspecials2NoSlash, false);
+            }
+        }
+
+        // Secure
+        if (isSecure) {
+          buf.append ("; Secure");
+        }
+        
+        // HttpOnly
+        if (isHttpOnly) {
+            buf.append("; HttpOnly");
+        }
+        headerBuf.append(buf);
+    }
+
+    public static boolean alreadyQuoted (String value) {
+        if (value==null || value.length()==0) return false;
+        return (value.charAt(0)=='\"' && value.charAt(value.length()-1)=='\"');
+    }
+    
+    /**
+     * Quotes values using rules that vary depending on Cookie version.
+     * @param version
+     * @param buf
+     * @param value
+     */
+    public static int maybeQuote2 (int version, StringBuffer buf, String 
value) {
+        return maybeQuote2(version,buf,value,false);
+    }
+
+    public static int maybeQuote2 (int version, StringBuffer buf, String 
value, boolean allowVersionSwitch) {
+        return maybeQuote2(version,buf,value,null,allowVersionSwitch);
+    }
+
+    public static int maybeQuote2 (int version, StringBuffer buf, String 
value, String literals, boolean allowVersionSwitch) {
+        if (value==null || value.length()==0) {
+            buf.append("\"\"");
+        }else if (containsCTL(value,version)) 
+            throw new IllegalArgumentException("Control character in cookie 
value, consider BASE64 encoding your value");
+        else if (alreadyQuoted(value)) {
+            buf.append('"');
+            buf.append(escapeDoubleQuotes(value,1,value.length()-1));
+            buf.append('"');
+        } else if (allowVersionSwitch && (!STRICT_SERVLET_COMPLIANCE) && 
version==0 && !isToken2(value, literals)) {
+            buf.append('"');
+            buf.append(escapeDoubleQuotes(value,0,value.length()));
+            buf.append('"');
+            version = 1;
+        } else if (version==0 && !isToken(value,literals)) {
+            buf.append('"');
+            buf.append(escapeDoubleQuotes(value,0,value.length()));
+            buf.append('"');
+        } else if (version==1 && !isToken2(value,literals)) {
+            buf.append('"');
+            buf.append(escapeDoubleQuotes(value,0,value.length()));
+            buf.append('"');
+        }else {
+            buf.append(value);
+        }
+        return version;
+    }
+
+
+    /**
+     * Escapes any double quotes in the given string.
+     *
+     * @param s the input string
+     * @param beginIndex start index inclusive
+     * @param endIndex exclusive
+     * @return The (possibly) escaped string
+     */
+    private static String escapeDoubleQuotes(String s, int beginIndex, int 
endIndex) {
+
+        if (s == null || s.length() == 0 || s.indexOf('"') == -1) {
+            return s;
+        }
+
+        StringBuffer b = new StringBuffer();
+        for (int i = beginIndex; i < endIndex; i++) {
+            char c = s.charAt(i);
+            if (c == '\\' ) {
+                b.append(c);
+                //ignore the character after an escape, just append it
+                if (++i>=endIndex) throw new IllegalArgumentException("Invalid 
escape character in cookie value.");
+                b.append(s.charAt(i));
+            } else if (c == '"')
+                b.append('\\').append('"');
+            else
+                b.append(c);
+        }
+
+        return b.toString();
+    }
+
+    /**
+     * Unescapes any double quotes in the given cookie value.
+     *
+     * @param bc The cookie value to modify
+     */
+    public static void unescapeDoubleQuotes(BBuffer bc) {
+
+        if (bc == null || bc.getLength() == 0 || bc.indexOf('"', 0) == -1) {
+            return;
+        }
+
+        int src = bc.getStart();
+        int end = bc.getEnd();
+        int dest = src;
+        byte[] buffer = bc.array();
+        
+        while (src < end) {
+            if (buffer[src] == '\\' && src < end && buffer[src+1]  == '"') {
+                src++;
+            }
+            buffer[dest] = buffer[src];
+            dest ++;
+            src ++;
+        }
+        bc.setEnd(dest);
+    }
+    
+    /*
+    List of Separator Characters (see isSeparator())
+    Excluding the '/' char violates the RFC, but 
+    it looks like a lot of people put '/'
+    in unquoted values: '/': ; //47 
+    '\t':9 ' ':32 '\"':34 '\'':39 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60 
+    '=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125
+    */
+    public static final char SEPARATORS[] = { '\t', ' ', '\"', '\'', '(', ')', 
',', 
+        ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
+
+    protected static final boolean separators[] = new boolean[128];
+    static {
+        for (int i = 0; i < 128; i++) {
+            separators[i] = false;
+        }
+        for (int i = 0; i < SEPARATORS.length; i++) {
+            separators[SEPARATORS[i]] = true;
+        }
+    }
+
+    /** Add all Cookie found in the headers of a request.
+     */
+    public  static void processCookies(List<ServerCookie> cookies,
+            List<ServerCookie> cookiesCache,
+            HttpMessage.HttpMessageBytes msgBytes ) {
+        
+        // process each "cookie" header
+        for (int i = 0; i < msgBytes.headerCount; i++) {
+            if (msgBytes.getHeaderName(i).equalsIgnoreCase("Cookie")) {
+                BBuffer bc = msgBytes.getHeaderValue(i);
+                if (bc.remaining() == 0) {
+                    continue;
+                }
+                processCookieHeader(cookies, cookiesCache,
+                        bc.array(),
+                        bc.getOffset(),
+                        bc.getLength());
+                
+            }
+
+        }
+    }
+    
+    /**
+     * Returns true if the byte is a separator character as
+     * defined in RFC2619. Since this is called often, this
+     * function should be organized with the most probable
+     * outcomes first.
+     * JVK
+     */
+    private static final boolean isSeparator(final byte c) {
+         if (c > 0 && c < 126)
+             return separators[c];
+         else
+             return false;
+    }
+    
+    /**
+     * Returns true if the byte is a whitespace character as
+     * defined in RFC2619
+     * JVK
+     */
+    private static final boolean isWhiteSpace(final byte c) {
+        // This switch statement is slightly slower
+        // for my vm than the if statement.
+        // Java(TM) 2 Runtime Environment, Standard Edition (build 
1.5.0_07-164)
+        /* 
+        switch (c) {
+        case ' ':;
+        case '\t':;
+        case '\n':;
+        case '\r':;
+        case '\f':;
+            return true;
+        default:;
+            return false;
+        }
+        */
+       if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f')
+           return true;
+       else
+           return false;
+    }
+
+    /**
+     * Parses a cookie header after the initial "Cookie:"
+     * [WS][$]token[WS]=[WS](token|QV)[;|,]
+     * RFC 2965
+     * JVK
+     */
+    public static final void processCookieHeader(
+            List<ServerCookie> cookies,
+            List<ServerCookie> cookiesCache,
+            byte bytes[], int off, int len){
+        if( len<=0 || bytes==null ) return;
+        int end=off+len;
+        int pos=off;
+        int nameStart=0;
+        int nameEnd=0;
+        int valueStart=0;
+        int valueEnd=0;
+        int version = 0;
+        ServerCookie sc=null;
+        boolean isSpecial;
+        boolean isQuoted;
+
+        while (pos < end) {
+            isSpecial = false;
+            isQuoted = false;
+
+            // Skip whitespace and non-token characters (separators)
+            while (pos < end && 
+                   (isSeparator(bytes[pos]) || isWhiteSpace(bytes[pos]))) 
+                {pos++; } 
+
+            if (pos >= end)
+                return;
+
+            // Detect Special cookies
+            if (bytes[pos] == '$') {
+                isSpecial = true;
+                pos++;
+            }
+
+            // Get the cookie name. This must be a token            
+            valueEnd = valueStart = nameStart = pos; 
+            pos = nameEnd = getTokenEndPosition(bytes,pos,end);
+
+            // Skip whitespace
+            while (pos < end && isWhiteSpace(bytes[pos])) {pos++; } 
+         
+
+            // Check for an '=' -- This could also be a name-only
+            // cookie at the end of the cookie header, so if we
+            // are past the end of the header, but we have a name
+            // skip to the name-only part.
+            if (pos < end && bytes[pos] == '=') {                
+
+                // Skip whitespace
+                do {
+                    pos++;
+                } while (pos < end && isWhiteSpace(bytes[pos])); 
+
+                if (pos >= end)
+                    return;
+
+                // Determine what type of value this is, quoted value,
+                // token, name-only with an '=', or other (bad)
+                switch (bytes[pos]) {
+                case '"': // Quoted Value
+                    isQuoted = true;
+                    valueStart=pos + 1; // strip "
+                    // getQuotedValue returns the position before 
+                    // at the last qoute. This must be dealt with
+                    // when the bytes are copied into the cookie
+                    valueEnd=getQuotedValueEndPosition(bytes, 
+                                                       valueStart, end);
+                    // We need pos to advance
+                    pos = valueEnd; 
+                    // Handles cases where the quoted value is 
+                    // unterminated and at the end of the header, 
+                    // e.g. [myname="value]
+                    if (pos >= end)
+                        return;
+                    break;
+                case ';':
+                case ',':
+                    // Name-only cookie with an '=' after the name token
+                    // This may not be RFC compliant
+                    valueStart = valueEnd = -1;
+                    // The position is OK (On a delimiter)
+                    break;
+                default:
+                    if (!isSeparator(bytes[pos])) {
+                        // Token
+                        valueStart=pos;
+                        // getToken returns the position at the delimeter
+                        // or other non-token character
+                        valueEnd=getTokenEndPosition(bytes, valueStart, end);
+                        // We need pos to advance
+                        pos = valueEnd;
+                    } else  {
+                        // INVALID COOKIE, advance to next delimiter
+                        // The starting character of the cookie value was
+                        // not valid.
+                        //log("Invalid cookie. Value not a token or quoted 
value");
+                        while (pos < end && bytes[pos] != ';' && 
+                               bytes[pos] != ',') 
+                            {pos++; }
+                        pos++;
+                        // Make sure no special avpairs can be attributed to 
+                        // the previous cookie by setting the current cookie
+                        // to null
+                        sc = null;
+                        continue;                        
+                    }
+                }
+            } else {
+                // Name only cookie
+                valueStart = valueEnd = -1;
+                pos = nameEnd;
+
+            }
+          
+            // We should have an avpair or name-only cookie at this
+            // point. Perform some basic checks to make sure we are
+            // in a good state.
+  
+            // Skip whitespace
+            while (pos < end && isWhiteSpace(bytes[pos])) {pos++; }
+
+
+            // Make sure that after the cookie we have a separator. This
+            // is only important if this is not the last cookie pair
+            while (pos < end && bytes[pos] != ';' && bytes[pos] != ',') { 
+                pos++;
+            }
+            
+            pos++;
+
+            /*
+            if (nameEnd <= nameStart || valueEnd < valueStart ) {
+                // Something is wrong, but this may be a case
+                // of having two ';' characters in a row.
+                // log("Cookie name/value does not conform to RFC 2965");
+                // Advance to next delimiter (ignoring everything else)
+                while (pos < end && bytes[pos] != ';' && bytes[pos] != ',') 
+                    { pos++; };
+                pos++;
+                // Make sure no special cookies can be attributed to 
+                // the previous cookie by setting the current cookie
+                // to null
+                sc = null;
+                continue;
+            }
+            */
+
+            // All checks passed. Add the cookie, start with the 
+            // special avpairs first
+            if (isSpecial) {
+                isSpecial = false;
+                // $Version must be the first avpair in the cookie header
+                // (sc must be null)
+                if (equals( "Version", bytes, nameStart, nameEnd) && 
+                    sc == null) {
+                    // Set version
+                    if( bytes[valueStart] =='1' && valueEnd == (valueStart+1)) 
{
+                        version=1;
+                    } else {
+                        // unknown version (Versioning is not very strict)
+                    }
+                    continue;
+                } 
+                
+                // We need an active cookie for Path/Port/etc.
+                if (sc == null) {
+                    continue;
+                }
+
+                // Domain is more common, so it goes first
+                if (equals( "Domain", bytes, nameStart, nameEnd)) {
+                    sc.getDomain().setBytes( bytes,
+                                           valueStart,
+                                           valueEnd-valueStart);
+                    continue;
+                } 
+
+                if (equals( "Path", bytes, nameStart, nameEnd)) {
+                    sc.getPath().setBytes( bytes,
+                                           valueStart,
+                                           valueEnd-valueStart);
+                    continue;
+                } 
+
+
+                if (equals( "Port", bytes, nameStart, nameEnd)) {
+                    // sc.getPort is not currently implemented.
+                    // sc.getPort().setBytes( bytes,
+                    //                        valueStart,
+                    //                        valueEnd-valueStart );
+                    continue;
+                } 
+
+                // Unknown cookie, complain
+                //log("Unknown Special Cookie");
+
+            } else { // Normal Cookie
+                // use a previous value from cache, if any (to avoid GC - 
tomcat 
+                // legacy )
+                if (cookiesCache.size() > cookies.size()) {
+                    sc = cookiesCache.get(cookies.size());
+                    cookies.add(sc);
+                } else {
+                    sc = new ServerCookie();
+                    cookiesCache.add(sc);
+                    cookies.add(sc);
+                }
+                sc.setVersion( version );
+                sc.getName().append( bytes, nameStart,
+                                       nameEnd-nameStart);
+                
+                if (valueStart != -1) { // Normal AVPair
+                    sc.getValue().append( bytes, valueStart,
+                            valueEnd-valueStart);
+                    if (isQuoted) {
+                        // We know this is a byte value so this is safe
+                        ServerCookie.unescapeDoubleQuotes(
+                                sc.getValue());
+                    }
+                } else {
+                    // Name Only
+                    sc.getValue().recycle(); 
+                }
+                sc.nameC.recycle();
+                sc.nameC.append(sc.getName());
+                continue;
+            }
+        }
+    }
+
+    /**
+     * Given the starting position of a token, this gets the end of the
+     * token, with no separator characters in between.
+     * JVK
+     */
+    private static final int getTokenEndPosition(byte bytes[], int off, int 
end){
+        int pos = off;
+        while (pos < end && !isSeparator(bytes[pos])) {pos++; }
+        
+        if (pos > end)
+            return end;
+        return pos;
+    }
+
+    /** 
+     * Given a starting position after an initial quote chracter, this gets
+     * the position of the end quote. This escapes anything after a '\' char
+     * JVK RFC 2616
+     */
+    private static final int getQuotedValueEndPosition(byte bytes[], int off, 
int end){
+        int pos = off;
+        while (pos < end) {
+            if (bytes[pos] == '"') {
+                return pos;                
+            } else if (bytes[pos] == '\\' && pos < (end - 1)) {
+                pos+=2;
+            } else {
+                pos++;
+            }
+        }
+        // Error, we have reached the end of the header w/o a end quote
+        return end;
+    }
+    
+    
+    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;
+    }
+    
+}
+

Propchange: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ServerCookie.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/http/package.html
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/http/package.html?rev=884412&view=auto
==============================================================================
    (empty)

Propchange: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/http/package.html
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to