Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   //
   //  ========================================================================
   //  Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
   //  ------------------------------------------------------------------------
   //  All rights reserved. This program and the accompanying materials
   //  are made available under the terms of the Eclipse Public License v1.0
   //  and Apache License v2.0 which accompanies this distribution.
   //
   //      The Eclipse Public License is available at
  //      http://www.eclipse.org/legal/epl-v10.html
  //
  //      The Apache License v2.0 is available at
  //      http://www.opensource.org/licenses/apache2.0.php
  //
  //  You may elect to redistribute this code under either of these licenses.
  //  ========================================================================
  //
  
  package org.eclipse.jetty.http;
  
  import java.util.Date;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Locale;
  import java.util.Map;
  
  
  /* ------------------------------------------------------------ */
HTTP Fields. A collection of HTTP header and or Trailer fields.

This class is not synchronized as it is expected that modifications will only be performed by a single thread.

  
  public class HttpFields
  {
      private static final Logger LOG = Log.getLogger(HttpFields.class);
      
      /* ------------------------------------------------------------ */
      public static final String __COOKIE_DELIM="\"\\\n\r\t\f\b%+ ;=";
      public static final TimeZone __GMT = TimeZone.getTimeZone("GMT");
      public static final BufferDateCache __dateCache = new BufferDateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'".);
  
      /* -------------------------------------------------------------- */
      static
      {
          .setID("GMT");
          .setTimeZone();
      }
      
      /* ------------------------------------------------------------ */
      public final static String __separators = ", \t";
  
      /* ------------------------------------------------------------ */
      private static final String[] DAYS =
      { "Sat""Sun""Mon""Tue""Wed""Thu""Fri""Sat"};
      private static final String[] MONTHS =
      { "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec""Jan"};
  
      
      /* ------------------------------------------------------------ */
      private static class DateGenerator
      {
          private final StringBuilder buf = new StringBuilder(32);
          private final GregorianCalendar gc = new GregorianCalendar();
        
        
Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
  
          public String formatDate(long date)
         {
             .setLength(0);
             .setTimeInMillis(date);
             
             int day_of_week = .get(.);
             int day_of_month = .get(.);
             int month = .get(.);
             int year = .get(.);
             int century = year / 100;
             year = year % 100;
             
             int hours = .get(.);
             int minutes = .get(.);
             int seconds = .get(.);
 
             .append([day_of_week]);
             .append(',');
             .append(' ');
             StringUtil.append2digits(day_of_month);
 
             .append(' ');
             .append([month]);
             .append(' ');
             StringUtil.append2digits(century);
             StringUtil.append2digits(year);
             
             .append(' ');
             StringUtil.append2digits(hours);
             .append(':');
             StringUtil.append2digits(minutes);
             .append(':');
             StringUtil.append2digits(seconds);
             .append(" GMT");
             return .toString();
         }
 
         /* ------------------------------------------------------------ */
        
Format "EEE, dd-MMM-yy HH:mm:ss 'GMT'" for cookies
 
         public void formatCookieDate(StringBuilder buflong date)
         {
             .setTimeInMillis(date);
             
             int day_of_week = .get(.);
             int day_of_month = .get(.);
             int month = .get(.);
             int year = .get(.);
             year = year % 10000;
 
             int epoch = (int) ((date / 1000) % (60 * 60 * 24));
             int seconds = epoch % 60;
             epoch = epoch / 60;
             int minutes = epoch % 60;
             int hours = epoch / 60;
 
             buf.append([day_of_week]);
             buf.append(',');
             buf.append(' ');
             StringUtil.append2digits(bufday_of_month);
 
             buf.append('-');
             buf.append([month]);
             buf.append('-');
             StringUtil.append2digits(bufyear/100);
             StringUtil.append2digits(bufyear%100);
             
             buf.append(' ');
             StringUtil.append2digits(bufhours);
             buf.append(':');
             StringUtil.append2digits(bufminutes);
             buf.append(':');
             StringUtil.append2digits(bufseconds);
             buf.append(" GMT");
         }
     }
 
     /* ------------------------------------------------------------ */
     private static final ThreadLocal<DateGenerator__dateGenerator =new ThreadLocal<DateGenerator>()
     {
         @Override
         protected DateGenerator initialValue()
         {
             return new DateGenerator();
         }
     };
     
     /* ------------------------------------------------------------ */
    
Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
 
     public static String formatDate(long date)
     {
         return .get().formatDate(date);
     }
 
     /* ------------------------------------------------------------ */
    
Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies
 
     public static void formatCookieDate(StringBuilder buflong date)
     {
         .get().formatCookieDate(buf,date);
     }
     
     /* ------------------------------------------------------------ */
    
Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies
 
     public static String formatCookieDate(long date)
     {
         StringBuilder buf = new StringBuilder(28);
         formatCookieDate(bufdate);
         return buf.toString();
     }
 
     /* ------------------------------------------------------------ */
     private final static String __dateReceiveFmt[] =
     {   
         "EEE, dd MMM yyyy HH:mm:ss zzz"
         "EEE, dd-MMM-yy HH:mm:ss",
         "EEE MMM dd HH:mm:ss yyyy",
 
         "EEE, dd MMM yyyy HH:mm:ss""EEE dd MMM yyyy HH:mm:ss zzz"
         "EEE dd MMM yyyy HH:mm:ss""EEE MMM dd yyyy HH:mm:ss zzz""EEE MMM dd yyyy HH:mm:ss"
         "EEE MMM-dd-yyyy HH:mm:ss zzz""EEE MMM-dd-yyyy HH:mm:ss""dd MMM yyyy HH:mm:ss zzz"
         "dd MMM yyyy HH:mm:ss""dd-MMM-yy HH:mm:ss zzz""dd-MMM-yy HH:mm:ss""MMM dd HH:mm:ss yyyy zzz"
         "MMM dd HH:mm:ss yyyy""EEE MMM dd HH:mm:ss yyyy zzz",  
         "EEE, MMM dd HH:mm:ss yyyy zzz""EEE, MMM dd HH:mm:ss yyyy""EEE, dd-MMM-yy HH:mm:ss zzz"
         "EEE dd-MMM-yy HH:mm:ss zzz""EEE dd-MMM-yy HH:mm:ss",
     };
 
     /* ------------------------------------------------------------ */
     private static class DateParser
     {
  
         long parse(final String dateVal)
         {
             for (int i = 0; i < .i++)
             {
                 if ([i] == null)
                 {
                     [i] = new SimpleDateFormat([i], .);
                     [i].setTimeZone();
                 }
 
                 try
                 {
                     Date date = (Date[i].parseObject(dateVal);
                     return date.getTime();
                 }
                 catch (java.lang.Exception e)
                 {
                     // LOG.ignore(e);
                 }
             }
             
             if (dateVal.endsWith(" GMT"))
             {
                 final String val = dateVal.substring(0, dateVal.length() - 4);
 
                 for (int i = 0; i < .i++)
                 {
                     try
                     {
                         Date date = (Date[i].parseObject(val);
                         return date.getTime();
                     }
                     catch (java.lang.Exception e)
                     {
                         // LOG.ignore(e);
                     }
                 }
             }    
             return -1;
         }
     }
 
     /* ------------------------------------------------------------ */
     public static long parseDate(String date)
     {
         return .get().parse(date);
     }
 
     /* ------------------------------------------------------------ */
     private static final ThreadLocal<DateParser__dateParser =new ThreadLocal<DateParser>()
     {
         @Override
         protected DateParser initialValue()
         {
             return new DateParser();
         }
     };
 
     /* -------------------------------------------------------------- */
     public final static String __01Jan1970=formatDate(0);
     public final static Buffer __01Jan1970_BUFFER=new ByteArrayBuffer();
     public final static String __01Jan1970_COOKIE = formatCookieDate(0).trim();
 
     /* -------------------------------------------------------------- */
     private final ArrayList<Field_fields = new ArrayList<Field>(20);
     private final HashMap<Buffer,Field_names = new HashMap<Buffer,Field>(32);
     
     /* ------------------------------------------------------------ */
    
Constructor.
 
     public HttpFields()
     {
     }
 
     // TODO externalize this cache so it can be configurable
     private static ConcurrentMap<StringBuffer__cache = new ConcurrentHashMap<StringBuffer>();
     private static int __cacheSize = Integer.getInteger("org.eclipse.jetty.http.HttpFields.CACHE",2000);
     
     /* -------------------------------------------------------------- */
     private Buffer convertValue(String value)
     {
         Buffer buffer = .get(value);
         if (buffer!=null)
             return buffer;
         
         try
         {   
             buffer = new ByteArrayBuffer(value,.);
             
             if (>0)
             {
                 if (.size()>)
                     .clear();
                 Buffer b=.putIfAbsent(value,buffer);
                 if (b!=null)
                     buffer=b;
             }
             
             return buffer;
         }
         catch (UnsupportedEncodingException e)
         {
             throw new RuntimeException(e);
         }
     }
     
     /* -------------------------------------------------------------- */
    
Get Collection of header names.
 
     {
         final List<Stringlist = new ArrayList<String>(.size());
 
 	for (Field f : )
 	{
 	    if (f!=null)
 	        list.add(BufferUtil.to8859_1_String(f._name));
 	}
 	return list;
     }
     
     /* -------------------------------------------------------------- */
    
Get enumeration of header _names. Returns an enumeration of strings representing the header _names for this request.
 
     public Enumeration<StringgetFieldNames()
     {
         final Enumeration<?> buffers = Collections.enumeration(.keySet());
         return new Enumeration<String>()
         {
             public String nextElement()
             {
                 return buffers.nextElement().toString();
             }
             
             public boolean hasMoreElements()
             {
                 return buffers.hasMoreElements();
             }
         }; 
     }
     
     /* ------------------------------------------------------------ */
     public int size()
     {
         return .size();
     }
     
     /* ------------------------------------------------------------ */
    
Get a Field by index.

Returns:
A Field value or null if the Field value has not been set
 
     public Field getField(int i)
     {
         return .get(i);
     }
 
     /* ------------------------------------------------------------ */
     private Field getField(String name)
     {
         return .get(..lookup(name));
     }
 
     /* ------------------------------------------------------------ */
     private Field getField(Buffer name)
     {
         return .get(..lookup(name));
     }
 
     /* ------------------------------------------------------------ */
     public boolean containsKey(Buffer name)
     {
         return .containsKey(..lookup(name));
     }
 
     /* ------------------------------------------------------------ */
     public boolean containsKey(String name)
     {
         return .containsKey(..lookup(name));
     }
 
     /* -------------------------------------------------------------- */
    

Parameters:
name the case-insensitive field name
Returns:
the value of a field, or null if not found. For multiple fields of the same name, only the first is returned.
 
     public String getStringField(String name)
     {
         Field field = getField(name);
         return field==null?null:field.getValue();
     }
 
     /* -------------------------------------------------------------- */
    

Parameters:
name the case-insensitive field name
Returns:
the value of a field, or null if not found. For multiple fields of the same name, only the first is returned.
 
     public String getStringField(Buffer name)
     {
         Field field = getField(name);
         return field==null?null:field.getValue();
     }
 
     /* -------------------------------------------------------------- */
    

Parameters:
name the case-insensitive field name
Returns:
the value of a field, or null if not found. For multiple fields of the same name, only the first is returned.
 
     public Buffer get(Buffer name)
     {
         Field field = getField(name);
         return field==null?null:field._value;
     }
 
 
     /* -------------------------------------------------------------- */
    
Get multi headers

Parameters:
name the case-insensitive field name
Returns:
Enumeration of the values, or null if no such header.
 
     public Collection<StringgetValuesCollection(String name)
     {
         Field field = getField(name);
 	if (field==null)
 	    return null;
 
         final List<Stringlist = new ArrayList<String>();
 
 	while(field!=null)
 	{
 	    list.add(field.getValue());
 	    field=field._next;
 	}
 	return list;
     }
 
     /* -------------------------------------------------------------- */
    
Get multi headers

Parameters:
name the case-insensitive field name
Returns:
Enumeration of the values
 
     public Enumeration<StringgetValues(String name)
     {
         final Field field = getField(name);
         if (field == null
         {
             List<Stringempty=Collections.emptyList();
             return Collections.enumeration(empty);
         }
 
         return new Enumeration<String>()
         {
             Field f = field;
 
             public boolean hasMoreElements()
             {
                 return  != null;
             }
 
             public String nextElement() throws NoSuchElementException
             {
                 if ( == nullthrow new NoSuchElementException();
                 Field n = ;
                  = .;
                 return n.getValue();
             }
         };
     }
 
     /* -------------------------------------------------------------- */
    
Get multi headers

Parameters:
name the case-insensitive field name
Returns:
Enumeration of the value Strings
 
     public Enumeration<StringgetValues(Buffer name)
     {
         final Field field = getField(name);
         if (field == null
         {
             List<Stringempty=Collections.emptyList();
             return Collections.enumeration(empty);
         }
 
         return new Enumeration<String>()
         {
             Field f = field;
 
             public boolean hasMoreElements()
             {
                 return  != null;
             }
 
             public String nextElement() throws NoSuchElementException
             {
                 if ( == nullthrow new NoSuchElementException();
                 Field n = ;
                  = .;
                 return n.getValue();
             }
         };
     }
 
     /* -------------------------------------------------------------- */
    
Get multi field values with separator. The multiple values can be represented as separate headers of the same name, or by a single header using the separator(s), or a combination of both. Separators may be quoted.

Parameters:
name the case-insensitive field name
separators String of separators.
Returns:
Enumeration of the values, or null if no such header.
 
     public Enumeration<StringgetValues(String namefinal String separators)
     {
         final Enumeration<Stringe = getValues(name);
         if (e == null
             return null;
         return new Enumeration<String>()
         {
             QuotedStringTokenizer tok = null;
 
             public boolean hasMoreElements()
             {
                 if ( != null && .hasMoreElements()) return true;
                 while (e.hasMoreElements())
                 {
                     String value = e.nextElement();
                      = new QuotedStringTokenizer(valueseparatorsfalsefalse);
                     if (.hasMoreElements()) return true;
                 }
                  = null;
                 return false;
             }
 
             public String nextElement() throws NoSuchElementException
             {
                 if (!hasMoreElements()) throw new NoSuchElementException();
                 String next = (String.nextElement();
                 if (next != nullnext = next.trim();
                 return next;
             }
         };
     }
 
     
     /* -------------------------------------------------------------- */
    
Set a field.

Parameters:
name the name of the field
value the value of the field. If null the field is cleared.
 
     public void put(String nameString value)
     {
         if (value==null)
             remove(name);
         else
         {
             Buffer n = ..lookup(name);
             Buffer v = convertValue(value);
             put(nv);
         }
     }
 
     /* -------------------------------------------------------------- */
    
Set a field.

Parameters:
name the name of the field
value the value of the field. If null the field is cleared.
 
     public void put(Buffer nameString value)
     {
         Buffer n = ..lookup(name);
         Buffer v = convertValue(value);
         put(nv);
     }
 
     /* -------------------------------------------------------------- */
    
Set a field.

Parameters:
name the name of the field
value the value of the field. If null the field is cleared.
 
     public void put(Buffer nameBuffer value)
     {
         remove(name);
         if (value == null)
             return;
 
         if (!(name instanceof BufferCache.CachedBuffer)) 
             name = ..lookup(name);
         if (!(value instanceof CachedBuffer))
             value..lookup(value).asImmutableBuffer();
         
         // new value;
         Field field = new Field(namevalue);
         .add(field);
         .put(namefield);
     }
 
     /* -------------------------------------------------------------- */
    
Set a field.

Parameters:
name the name of the field
list the List value of the field. If null the field is cleared.
 
     public void put(String nameList<?> list)
     {
         if (list == null || list.size() == 0)
         {
             remove(name);
             return;
         }
         Buffer n = ..lookup(name);
 
         Object v = list.get(0);
         if (v != null)
             put(n..lookup(v.toString()));
         else
             remove(n);
 
         if (list.size() > 1)
         {
             java.util.Iterator<?> iter = list.iterator();
             iter.next();
             while (iter.hasNext())
             {
                 v = iter.next();
                 if (v != nullput(n..lookup(v.toString()));
             }
         }
     }
 
     /* -------------------------------------------------------------- */
    
Add to or set a field. If the field is allowed to have multiple values, add will add multiple headers of the same name.

Parameters:
name the name of the field
value the value of the field.
Throws:
java.lang.IllegalArgumentException If the name is a single valued field and already has a value.
 
     public void add(String nameString valuethrows IllegalArgumentException
     {
         if (value==null)
             return;
         Buffer n = ..lookup(name);
         Buffer v = convertValue(value);
         add(nv);
     }
 
     /* -------------------------------------------------------------- */
    
Add to or set a field. If the field is allowed to have multiple values, add will add multiple headers of the same name.

Parameters:
name the name of the field
value the value of the field.
Throws:
java.lang.IllegalArgumentException If the name is a single valued field and already has a value.
 
     public void add(Buffer nameBuffer valuethrows IllegalArgumentException
     {   
         if (value == nullthrow new IllegalArgumentException("null value");
 
         if (!(name instanceof CachedBuffer))
             name = ..lookup(name);
         name=name.asImmutableBuffer();
         
         if (!(value instanceof CachedBuffer) && HttpHeaderValues.hasKnownValues(..getOrdinal(name)))
             value..lookup(value);
         value=value.asImmutableBuffer();
         
         Field field = .get(name);
         Field last = null;
         while (field != null)
         {
             last = field;
             field = field._next;
         }
 
         // create the field
         field = new Field(namevalue);
         .add(field);
 
         // look for chain to add too
         if (last != null)
             last._next = field;
         else
             .put(namefield);
     }
 
     /* ------------------------------------------------------------ */
    
Remove a field.

Parameters:
name
 
     public void remove(String name)
     {
         remove(..lookup(name));
     }
 
     /* ------------------------------------------------------------ */
    
Remove a field.

Parameters:
name
 
     public void remove(Buffer name)
     {
         if (!(name instanceof BufferCache.CachedBuffer)) 
             name = ..lookup(name);
         Field field = .remove(name);
         while (field != null)
         {
             .remove(field);
             field = field._next;
         }
     }
 
     /* -------------------------------------------------------------- */
    
Get a header as an long value. Returns the value of an integer field or -1 if not found. The case of the field name is ignored.

Parameters:
name the case-insensitive field name
Throws:
java.lang.NumberFormatException If bad long found
 
     public long getLongField(String namethrows NumberFormatException
     {
         Field field = getField(name);
         return field==null?-1L:field.getLongValue();
     }
 
     /* -------------------------------------------------------------- */
    
Get a header as an long value. Returns the value of an integer field or -1 if not found. The case of the field name is ignored.

Parameters:
name the case-insensitive field name
Throws:
java.lang.NumberFormatException If bad long found
 
     public long getLongField(Buffer namethrows NumberFormatException
     {
         Field field = getField(name);
         return field==null?-1L:field.getLongValue();
     }
 
     /* -------------------------------------------------------------- */
    
Get a header as a date value. Returns the value of a date field, or -1 if not found. The case of the field name is ignored.

Parameters:
name the case-insensitive field name
 
     public long getDateField(String name)
     {
         Field field = getField(name);
         if (field == null
             return -1;
 
         String val = valueParameters(BufferUtil.to8859_1_String(field._value), null);
         if (val == null
             return -1;
 
         final long date = .get().parse(val);
         if (date==-1)
             throw new IllegalArgumentException("Cannot convert date: " + val);
         return date;
     }
 
     /* -------------------------------------------------------------- */
    
Sets the value of an long field.

Parameters:
name the field name
value the field long value
 
     public void putLongField(Buffer namelong value)
     {
         Buffer v = BufferUtil.toBuffer(value);
         put(namev);
     }
 
     /* -------------------------------------------------------------- */
    
Sets the value of an long field.

Parameters:
name the field name
value the field long value
 
     public void putLongField(String namelong value)
     {
         Buffer n = ..lookup(name);
         Buffer v = BufferUtil.toBuffer(value);
         put(nv);
     }
 
     /* -------------------------------------------------------------- */
    
Sets the value of an long field.

Parameters:
name the field name
value the field long value
 
     public void addLongField(String namelong value)
     {
         Buffer n = ..lookup(name);
         Buffer v = BufferUtil.toBuffer(value);
         add(nv);
     }
 
     /* -------------------------------------------------------------- */
    
Sets the value of an long field.

Parameters:
name the field name
value the field long value
 
     public void addLongField(Buffer namelong value)
     {
         Buffer v = BufferUtil.toBuffer(value);
         add(namev);
     }
 
     /* -------------------------------------------------------------- */
    
Sets the value of a date field.

Parameters:
name the field name
date the field date value
 
     public void putDateField(Buffer namelong date)
     {
         String d=formatDate(date);
         Buffer v = new ByteArrayBuffer(d);
         put(namev);
     }
 
     /* -------------------------------------------------------------- */
    
Sets the value of a date field.

Parameters:
name the field name
date the field date value
 
     public void putDateField(String namelong date)
     {
         Buffer n = ..lookup(name);
         putDateField(n,date);
     }
 
     /* -------------------------------------------------------------- */
    
Sets the value of a date field.

Parameters:
name the field name
date the field date value
 
     public void addDateField(String namelong date)
     {
         String d=formatDate(date);
         Buffer n = ..lookup(name);
         Buffer v = new ByteArrayBuffer(d);
         add(nv);
     }
 
     /* ------------------------------------------------------------ */
    
Format a set cookie value

Parameters:
cookie The cookie.
 
     public void addSetCookie(HttpCookie cookie)
     {
         addSetCookie(
                 cookie.getName(),
                 cookie.getValue(),
                 cookie.getDomain(),
                 cookie.getPath(),
                 cookie.getMaxAge(),
                 cookie.getComment(),
                 cookie.isSecure(),
                 cookie.isHttpOnly(),
                 cookie.getVersion());
     }

    
Format a set cookie value

Parameters:
name the name
value the value
domain the domain
path the path
maxAge the maximum age
comment the comment (only present on versions > 0)
isSecure true if secure cookie
isHttpOnly true if for http only
version version of cookie logic to use (0 == default behavior)
 
     public void addSetCookie(
             final String name
             final String value
             final String domain,
             final String path
             final long maxAge,
             final String comment
             final boolean isSecure,
             final boolean isHttpOnly
             int version)
     {
     	String delim=;
     	
         // Check arguments
         if (name == null || name.length() == 0) 
             throw new IllegalArgumentException("Bad cookie name");
 
         // Format value and params
         StringBuilder buf = new StringBuilder(128);
         String name_value_params;
         QuotedStringTokenizer.quoteIfNeeded(bufnamedelim);
         buf.append('=');
         String start=buf.toString();
         boolean hasDomain = false;
         boolean hasPath = false;
         
         if (value != null && value.length() > 0)
             QuotedStringTokenizer.quoteIfNeeded(bufvaluedelim);        
 
         if (comment != null && comment.length() > 0)
         {
             buf.append(";Comment=");
             QuotedStringTokenizer.quoteIfNeeded(bufcommentdelim);
         }
 
         if (path != null && path.length() > 0)
         {
             hasPath = true;
             buf.append(";Path=");
             if (path.trim().startsWith("\""))
                 buf.append(path);
             else
                 QuotedStringTokenizer.quoteIfNeeded(buf,path,delim);
         }
        if (domain != null && domain.length() > 0)
        {
            hasDomain = true;
            buf.append(";Domain=");
            QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(.),delim);
        }
        if (maxAge >= 0)
        {
            // Always add the expires param as some browsers still don't handle max-age
            buf.append(";Expires=");
            if (maxAge == 0)
                buf.append();
            else
                formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge);
            if (version >0)
            {
                buf.append(";Max-Age=");
                buf.append(maxAge);
            }
        }
        if (isSecure)
            buf.append(";Secure");
        if (isHttpOnly
            buf.append(";HttpOnly");
        name_value_params = buf.toString();
        
        // remove existing set-cookie of same name
        Field field = getField(.);
        Field last=null;
        while (field!=null)
        {
            String val = (field._value == null ? null : field._value.toString());
            if (val!=null && val.startsWith(start))
            {
                //existing cookie has same name, does it also match domain and path?
                if (((!hasDomain && !val.contains("Domain")) || (hasDomain && val.contains("Domain="+domain))) &&
                    ((!hasPath && !val.contains("Path")) || (hasPath && val.contains("Path="+path))))
                {
                    .remove(field);
                    if (last==null)
                        .put(.,field._next);
                    else
                        last._next=field._next;
                    break;
                }
            }
            last=field;
            field=field._next;
        }
        add(.new ByteArrayBuffer(name_value_params));
        
        // Expire responses with set-cookie headers so they do not get cached.
    }
    /* -------------------------------------------------------------- */
    public void putTo(Buffer bufferthrows IOException
    {
        for (int i = 0; i < .size(); i++)
        {
            Field field = .get(i);
            if (field != null
                field.putTo(buffer);
        }
        BufferUtil.putCRLF(buffer);
    }
    /* -------------------------------------------------------------- */
    public String toString()
    {
        try
        {
            StringBuffer buffer = new StringBuffer();
            for (int i = 0; i < .size(); i++)
            {
                Field field = (Field.get(i);
                if (field != null)
                {
                    String tmp = field.getName();
                    if (tmp != nullbuffer.append(tmp);
                    buffer.append(": ");
                    tmp = field.getValue();
                    if (tmp != nullbuffer.append(tmp);
                    buffer.append("\r\n");
                }
            }
            buffer.append("\r\n");
            return buffer.toString();
        }
        catch (Exception e)
        {
            .warn(e);
            return e.toString();
        }
    }
    /* ------------------------------------------------------------ */
    
Clear the header.
    public void clear()
    {
        .clear();
        .clear();
    }
    /* ------------------------------------------------------------ */
    
Add fields from another HttpFields instance. Single valued fields are replaced, while all others are added.

Parameters:
fields
    public void add(HttpFields fields)
    {
        if (fields == nullreturn;
        Enumeration e = fields.getFieldNames();
        while (e.hasMoreElements())
        {
            String name = (Stringe.nextElement();
            Enumeration values = fields.getValues(name);
            while (values.hasMoreElements())
                add(name, (Stringvalues.nextElement());
        }
    }
    /* ------------------------------------------------------------ */
    
Get field value parameters. Some field values can have parameters. This method separates the value from the parameters and optionally populates a map with the parameters. For example:
 
 FieldName : Value ; param1=val1 ; param2=val2
 
 

Parameters:
value The Field value, possibly with parameteres.
parameters A map to populate with the parameters, or null
Returns:
The value.
    public static String valueParameters(String valueMap<String,Stringparameters)
    {
        if (value == nullreturn null;
        int i = value.indexOf(';');
        if (i < 0) return value;
        if (parameters == nullreturn value.substring(0, i).trim();
        StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";"falsetrue);
        while (tok1.hasMoreTokens())
        {
            String token = tok1.nextToken();
            StringTokenizer tok2 = new QuotedStringTokenizer(token"= ");
            if (tok2.hasMoreTokens())
            {
                String paramName = tok2.nextToken();
                String paramVal = null;
                if (tok2.hasMoreTokens()) paramVal = tok2.nextToken();
                parameters.put(paramNameparamVal);
            }
        }
        return value.substring(0, i).trim();
    }
    /* ------------------------------------------------------------ */
    private static final Float __one = new Float("1.0");
    private static final Float __zero = new Float("0.0");
    private static final StringMap __qualities = new StringMap();
    static
    {
        .put(null);
        .put("1.0");
        .put("1");
        .put("0.9"new Float("0.9"));
        .put("0.8"new Float("0.8"));
        .put("0.7"new Float("0.7"));
        .put("0.66"new Float("0.66"));
        .put("0.6"new Float("0.6"));
        .put("0.5"new Float("0.5"));
        .put("0.4"new Float("0.4"));
        .put("0.33"new Float("0.33"));
        .put("0.3"new Float("0.3"));
        .put("0.2"new Float("0.2"));
        .put("0.1"new Float("0.1"));
        .put("0");
        .put("0.0");
    }
    /* ------------------------------------------------------------ */
    public static Float getQuality(String value)
    {
        if (value == nullreturn ;
        int qe = value.indexOf(";");
        if (qe++ < 0 || qe == value.length()) return ;
        if (value.charAt(qe++) == 'q')
        {
            qe++;
            Map.Entry entry = .getEntry(valueqevalue.length() - qe);
            if (entry != nullreturn (Floatentry.getValue();
        }
        HashMap params = new HashMap(3);
        valueParameters(valueparams);
        String qs = (Stringparams.get("q");
        Float q = (Float.get(qs);
        if (q == null)
        {
            try
            {
                q = new Float(qs);
            }
            catch (Exception e)
            {
                q = ;
            }
        }
        return q;
    }
    /* ------------------------------------------------------------ */
    
List values in quality order.

Parameters:
e Enumeration of values with quality parameters
Returns:
values in quality order.
    public static List qualityList(Enumeration e)
    {
        if (e == null || !e.hasMoreElements()) return .;
        Object list = null;
        Object qual = null;
        // Assume list will be well ordered and just add nonzero
        while (e.hasMoreElements())
        {
            String v = e.nextElement().