All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sunlabs.brazil.util.http.MimeHeaders Maven / Gradle / Ivy

The newest version!
/*
 * MimeHeaders.java
 *
 * Brazil project web application toolkit,
 * export version: 2.3 
 * Copyright (c) 1999-2005 Sun Microsystems, Inc.
 *
 * Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License Version 
 * 1.0 (the "License"). You may not use this file except in compliance with 
 * the License. A copy of the License is included as the file "license.terms",
 * and also available at http://www.sun.com/
 * 
 * The Original Code is from:
 *    Brazil project web application toolkit release 2.3.
 * The Initial Developer of the Original Code is: cstevens.
 * Portions created by cstevens are Copyright (C) Sun Microsystems, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s): cstevens, suhler.
 *
 * Version:  2.4
 * Created by cstevens on 99/09/15
 * Last modified by suhler on 05/12/08 13:03:48
 *
 * Version Histories:
 *
 * 2.4 05/12/08-13:03:48 (suhler)
 *   add limits on request size to prevent DOS attacks
 *
 * 2.3 05/05/25-12:56:31 (suhler)
 *   added the ability to read new headers, replacing old ones
 *
 * 2.2 04/11/30-15:19:46 (suhler)
 *   fixed sccs version string
 *
 * 2.1 02/10/01-16:37:04 (suhler)
 *   version change
 *
 * 1.12 99/11/16-14:48:57 (cstevens)
 *   Bug used to cause continuation line to be added to the _first_ occurence of
 *   the key, not the most recent occurence (namely, the previous line).
 *
 * 1.11 99/10/26-18:56:28 (cstevens)
 *   Change MimeHeaders so it uses "put" instead of "set", to be compatible with
 *   names chosen by Hashtable and StringMap.
 *
 * 1.10 99/10/14-12:59:44 (cstevens)
 *   Documentation.
 *
 * 1.9 99/10/07-13:04:16 (cstevens)
 *   docs
 *
 * 1.8 99/10/04-17:16:44 (cstevens)
 *
 * 1.7 99/10/04-16:14:27 (cstevens)
 *   Merged changes between child workspace "/home/cstevens/ws/brazil/naws" and
 *   parent workspace "/export/ws/brazil/naws".
 *
 * 1.5.1.1 99/10/04-16:03:47 (cstevens)
 *   Documentation for LexML and StringMap.
 *
 * 1.6 99/10/01-11:23:07 (suhler)
 *   Merged changes between child workspace "/home/suhler/brazil/naws" and
 *   parent workspace "/net/mack.eng/export/ws/brazil/naws".
 *
 * 1.4.1.1 99/10/01-11:21:10 (suhler)
 *   added toString()
 *
 * 1.5 99/09/30-10:45:53 (cstevens)
 *   Easier for debugging.
 *
 * 1.4 99/09/15-15:56:46 (cstevens)
 *   efficiency
 *
 * 1.3 99/09/15-14:51:57 (cstevens)
 *   import *;
 *
 * 1.2 99/09/15-14:41:41 (cstevens)
 *   Rewritign http server to make it easier to proxy requests.
 *
 * 1.2 99/09/15-14:31:37 (Codemgr)
 *   SunPro Code Manager data about conflicts, renames, etc...
 *   Name history : 1 0 util/http/MimeHeaders.java
 *
 * 1.1 99/09/15-14:31:36 (cstevens)
 *   date and time created 99/09/15 14:31:36 by cstevens
 *
 */

package sunlabs.brazil.util.http;

import sunlabs.brazil.util.StringMap;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

/**
 * This class is build on top of the StringMap class and
 * provides added methods that are of help when manipulating MIME headers.
 * By creating an instance of this class, the user can conveniently read,
 * write, and modify MIME headers.
 *
 * @author      Colin Stevens ([email protected])
 * @version		2.4
 */

public class MimeHeaders
    extends StringMap
{
    /*
     * Place arbitrary limits on header size to mitigate DOS attacts.
     */

    public static final int MAX_LINE=1024;
    public static final int MAX_LINES=1024;

    /**
     * Creates a new, empty MimeHeaders object.
     */
    public
    MimeHeaders()
    {
    }

    /**
     * Creates a new MimeHeaders object and then initializes
     * it by reading MIME headers from the specified input stream.
     *
     * @param	in
     *		The input stream to read.
     */
    public
    MimeHeaders(HttpInputStream in)
	throws IOException
    {
	read(in);
    }

    /**
     * Reads MIME headers from the specified input stream.  This method
     * reads up to and consumes the blank line that marks the end of the
     * MIME headers.  It also stops reading if it reaches the end of
     * the input stream.
     * 

* The MIME headers read from the input stream are stored in this * MimeHeaders object. All headers read are added * to the existing headers; the new headers do not replace the * existing ones. The order of the headers in this object will * reflect the order of the headers from the input stream, but * space characters surrounding the keys and values are not preserved. *

* In a set of MIME headers, the given key may appear multiple times * (that is, on multiple lines, not necessarily consecutively). * In that case, that key will appear multiple times in this * MimeHeaders object also. The HTTP spec says that * if a given key appears multiple times in a set of MIME headers, the * values can be concatenated together with commas * between them. However, in practice, it appears that some browsers * and HTTP servers get confused when encountering such collapsed * MIME headers, for instance, the Yahoo mail reader program. *

* MIME headers also support the idea of continuation lines, where * a key (and optionally its value) is followed on subsequent line(s) by * another value without a key. The HTTP spec says that in this case * the values can be concatenated together with space characters * between them. In practice, joining continuation lines together * does not seem to confuse any browsers or HTTP servers. This method * joins continuation lines together by putting the space-equivalent * characters "\r\n\t" between the values so it can be easily parsed * with StringTokenizer and also easily written to * an output stream in a format that actually preserves its formatting * as a continuation line. * * @param in * The input stream to read from. * * @throws IOException * if the input stream throws an IOException while being * read. */ public void read(HttpInputStream in) throws IOException { read(in, false); } /** * Reads MIME headers from the specified input stream. * Same as (@link #read(HttpInputStream in)), only existing keys may * be replaced or augmented. * * @param in * The input stream to read from. * @param shouldReplace * If true, existing keys are replaced instead of * augmented. * * @throws IOException * if the input stream throws an IOException while being * read. * @see #read(HttpInputStream in) */ public void read(HttpInputStream in, boolean shouldReplace) throws IOException { int count=0; while (count++ < MAX_LINES) { String line = in.readLine(MAX_LINE); if ((line == null) || (line.length() == 0)) { break; } if (count >= MAX_LINES) { throw new IOException("Too many headers in HTTP request"); } if (Character.isSpaceChar(line.charAt(0)) == false) { int index = line.indexOf(':'); if (index >= 0) { String key = line.substring(0, index).trim(); String value = line.substring(index + 1).trim(); if (shouldReplace) { put(key, value); } else { add(key, value); } } } else if (size() > 0) { String value = get(size() - 1); put(size() - 1, value + "\r\n\t" + line.trim()); } } } /** * Writes this MimeHeaders object to the given output * stream. This method does not write a blank line after * the headers are written. * * @param out * The output stream. */ public void print(OutputStream out) { print(new PrintStream(out)); } /** * Writes this MimeHeaders object to the given output * stream. This method does not write a blank line after * the headers are written. * * @param out * The output stream. */ public void print(PrintStream out) { int length = size(); for (int i = 0; i < length; i++) { String key = getKey(i); String value = get(i); out.print(key + ": " + value + "\r\n"); } } /** * Maps the given case-insensitive key to the specified value if the * key does not already exist in this MimeHeaders object. *

* Often, when dealing with MIME headers, the user will want to set * a header only if that header is not already set. * * @param key * The new key. May not be null. * * @param value * The new value. May be null. */ public void putIfNotPresent(String key, String value) { if (get(key) == null) { put(key, value); } } /** * Maps the given case-insensitive key to the specified value in this * MimeHeaders object, replacing the old value. *

* This is convenience method that automatically converts the * integer value to a string before calling the underlying * put method. * * @param key * The new key. May not be null. * * @param value * The new value. */ public void put(String key, int value) { put(key, Integer.toString(value)); } /** * Adds a mapping for the given case-insensitive key to the specified * value in this MimeHeaders object. It leaves any existing * key-value mapping alone. *

* This is convenience method that automatically converts the * integer value to a string before calling the underlying * add method. * * @param key * The new key. May not be null. * * @param value * The new value. */ public void add(String key, int value) { add(key, Integer.toString(value)); } /** * Copies the contents of this MimeHeaders object, * {@link #add adding} all the other's keys and values to the other. * * @param other * The MimeHeaders object to copy to. */ public void copyTo(MimeHeaders other) { int length = size(); for (int i = 0; i < length; i++) { other.add(getKey(i), get(i)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy