You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by cr...@locus.apache.org on 2000/04/17 20:39:51 UTC

cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/util RequestUtil.java

craigmcc    00/04/17 11:39:50

  Modified:    proposals/catalina/src/share/org/apache/tomcat
                        HttpResponse.java Response.java
               proposals/catalina/src/share/org/apache/tomcat/connector
                        Constants.java HttpRequestBase.java
                        HttpResponseBase.java LocalStrings.properties
                        RequestBase.java ResponseBase.java
               proposals/catalina/src/share/org/apache/tomcat/connector/http
                        Constants.java HttpProcessor.java
                        HttpRequestImpl.java
               proposals/catalina/src/share/org/apache/tomcat/security
                        HttpBasicAuth.java
               proposals/catalina/src/share/org/apache/tomcat/util
                        RequestUtil.java
  Log:
  Flesh out the implementation of response handling for both generic and
  HTTP responses.
  
  Finish implementing parameter handling on HTTP requests (inadvertently
  omitted last time).
  
  Revision  Changes    Path
  1.2       +11 -4     jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/HttpResponse.java
  
  Index: HttpResponse.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/HttpResponse.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- HttpResponse.java	2000/04/14 19:41:48	1.1
  +++ HttpResponse.java	2000/04/17 18:39:47	1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/HttpResponse.java,v 1.1 2000/04/14 19:41:48 craigmcc Exp $
  - * $Revision: 1.1 $
  - * $Date: 2000/04/14 19:41:48 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/HttpResponse.java,v 1.2 2000/04/17 18:39:47 craigmcc Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/04/17 18:39:47 $
    *
    * ====================================================================
    *
  @@ -74,7 +74,7 @@
    * based on the processing of a corresponding <code>HttpRequest</code>.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.1 $ $Date: 2000/04/14 19:41:48 $
  + * @version $Revision: 1.2 $ $Date: 2000/04/17 18:39:47 $
    */
   
   public interface HttpResponse
  @@ -110,6 +110,13 @@
        * @param name Header name to look up
        */
       public Enumeration getHeaderValues(String name);
  +
  +
  +    /**
  +     * Return the error message that was set with <code>sendError()</code>
  +     * for this Response.
  +     */
  +    public String getMessage();
   
   
       /**
  
  
  
  1.5       +4 -14     jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Response.java
  
  Index: Response.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Response.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Response.java	2000/04/14 19:41:48	1.4
  +++ Response.java	2000/04/17 18:39:47	1.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Response.java,v 1.4 2000/04/14 19:41:48 craigmcc Exp $
  - * $Revision: 1.4 $
  - * $Date: 2000/04/14 19:41:48 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Response.java,v 1.5 2000/04/17 18:39:47 craigmcc Exp $
  + * $Revision: 1.5 $
  + * $Date: 2000/04/17 18:39:47 $
    *
    * ====================================================================
    *
  @@ -79,7 +79,7 @@
    * based on the processing of a corresponding <code>Request</code>.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.4 $ $Date: 2000/04/14 19:41:48 $
  + * @version $Revision: 1.5 $ $Date: 2000/04/17 18:39:47 $
    */
   
   public interface Response {
  @@ -170,16 +170,6 @@
        * @exception IOException if an input/output error occurs
        */
       public ServletOutputStream createOutputStream() throws IOException;
  -
  -
  -    /**
  -     * Ensure that the HTTP headers (and any buffered output) have been
  -     * flushed to the output stream, even if it was never acquired by
  -     * a servlet.
  -     *
  -     * @exception IOException if an input/output error occurs
  -     */
  -    public void flush() throws IOException;
   
   
       /**
  
  
  
  1.2       +5 -3      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/Constants.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Constants.java	2000/04/15 23:36:15	1.1
  +++ Constants.java	2000/04/17 18:39:47	1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/Constants.java,v 1.1 2000/04/15 23:36:15 craigmcc Exp $
  - * $Revision: 1.1 $
  - * $Date: 2000/04/15 23:36:15 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/Constants.java,v 1.2 2000/04/17 18:39:47 craigmcc Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/04/17 18:39:47 $
    *
    * ====================================================================
    *
  @@ -72,5 +72,7 @@
   public final class Constants {
   
       public static final String Package = "org.apache.tomcat.connector";
  +    public static final String SessionCookie = "JSESSIONID";
  +    public static final String SessionParameter = "jsessionid";
   
   }
  
  
  
  1.4       +179 -6    jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/HttpRequestBase.java
  
  Index: HttpRequestBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/HttpRequestBase.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- HttpRequestBase.java	2000/04/16 05:13:36	1.3
  +++ HttpRequestBase.java	2000/04/17 18:39:47	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/HttpRequestBase.java,v 1.3 2000/04/16 05:13:36 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/04/16 05:13:36 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/HttpRequestBase.java,v 1.4 2000/04/17 18:39:47 craigmcc Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/04/17 18:39:47 $
    *
    * ====================================================================
    *
  @@ -73,9 +73,12 @@
   import java.util.Enumeration;
   import java.util.Hashtable;
   import java.util.Vector;
  +import javax.servlet.RequestDispatcher;
  +import javax.servlet.ServletInputStream;
   import javax.servlet.http.Cookie;
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpSession;
  +import javax.servlet.http.HttpUtils;
   import org.apache.tomcat.HttpRequest;
   import org.apache.tomcat.Manager;
   import org.apache.tomcat.Realm;
  @@ -86,13 +89,13 @@
    * Convenience base implementation of the <b>HttpRequest</b> interface, which
    * can be used for the Request implementation required by most Connectors that
    * implement the HTTP protocol.  Only the connector-specific methods need to
  - * be implemented, which are marked abstract in this class.
  + * be implemented.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.3 $ $Date: 2000/04/16 05:13:36 $
  + * @version $Revision: 1.4 $ $Date: 2000/04/17 18:39:47 $
    */
   
  -public abstract class HttpRequestBase
  +public class HttpRequestBase
       extends RequestBase
       implements HttpRequest, HttpServletRequest {
   
  @@ -148,6 +151,14 @@
   
   
       /**
  +     * The parsed parameters for this request.  This is populated only if
  +     * parameter information is requested via one of the
  +     * <code>getParameter()</code> family of method calls.
  +     */
  +    protected Hashtable parameters = null;
  +
  +
  +    /**
        * The path information for this request.
        */
       protected String pathInfo = null;
  @@ -262,6 +273,7 @@
   	cookies.removeAllElements();
   	headers.clear();
   	method = null;
  +	parameters = null;
   	pathInfo = null;
   	queryString = null;
   	requestedSessionCookie = false;
  @@ -439,7 +451,168 @@
       }
   
   
  +    // ------------------------------------------------------ Protected Methods
  +
  +
  +    /**
  +     * Parse the parameters of this request, if it has not already occurred.
  +     * If parameters are present in both the query string and the request
  +     * content, they are merged.
  +     */
  +    protected void parseParameters() {
  +
  +	if (parameters != null)
  +	    return;
  +
  +	// Parse any query string parameters for this request
  +	Hashtable queryParameters = null;
  +	try {
  +	    queryParameters = HttpUtils.parseQueryString(getQueryString());
  +	} catch (IllegalArgumentException e) {
  +	    queryParameters = null;
  +	}
  +
  +	// Parse any posted parameters in the input stream
  +	Hashtable postParameters = null;
  +	if ("POST".equals(getMethod()) &&
  +	    "application/x-www-form-urlencoded".equals(getContentType())) {
  +	    try {
  +		ServletInputStream is = getInputStream();
  +		postParameters =
  +		    HttpUtils.parsePostData(getContentLength(), is);
  +	    } catch (IllegalArgumentException e) {
  +		postParameters = null;
  +	    } catch (IOException e) {
  +		postParameters = null;
  +	    }
  +
  +	    // Handle the simple cases that require no merging
  +	    if (queryParameters == null) {
  +		if (postParameters == null) {
  +		    parameters = new Hashtable();
  +		    return;
  +		} else {
  +		    parameters = postParameters;
  +		    return;
  +		}
  +	    } else if (postParameters == null) {
  +		parameters = queryParameters;
  +		return;
  +	    }
  +	}
  +
  +	// Merge the parameters retrieved from both sources
  +	parameters = queryParameters;
  +	Enumeration postKeys = postParameters.keys();
  +	while (postKeys.hasMoreElements()) {
  +	    String postKey = (String) postKeys.nextElement();
  +	    Object postValue = postParameters.get(postKey);
  +	    Object queryValue = parameters.get(postKey);
  +	    if (queryValue == null) {
  +		parameters.put(postKey, postValue);
  +		continue;
  +	    }
  +	    Vector newValues = new Vector();
  +	    if (queryValue instanceof String)
  +		newValues.addElement(queryValue);
  +	    else if (queryValue instanceof String[]) {
  +		String queryArray[] = (String[]) queryValue;
  +		for (int i = 0; i < queryArray.length; i++)
  +		    newValues.addElement(queryArray[i]);
  +	    }
  +	    if (postValue instanceof String)
  +		newValues.addElement(postValue);
  +	    else if (postValue instanceof String[]) {
  +		String postArray[] = (String[]) postValue;
  +		for (int i = 0; i < postArray.length; i++)
  +		    newValues.addElement(postArray[i]);
  +	    }
  +	}
  +
  +    }
  +
  +
       // ------------------------------------------------- ServletRequest Methods
  +
  +
  +    /**
  +     * Return the value of the specified request parameter, if any; otherwise,
  +     * return <code>null</code>.  If there is more than one value defined,
  +     * return only the first one.
  +     *
  +     * @param name Name of the desired request parameter
  +     */
  +    public String getParameter(String name) {
  +
  +	parseParameters();
  +	Object value = parameters.get(name);
  +	if (value == null)
  +	    return (null);
  +	else if (value instanceof String)
  +	    return ((String) value);
  +	else if (value instanceof String[])
  +	    return (((String[]) value)[0]);
  +	else
  +	    return (null);
  +
  +    }
  +
  +
  +    /**
  +     * Return the names of all defined request parameters for this request.
  +     */
  +    public Enumeration getParameterNames() {
  +
  +	parseParameters();
  +	return (parameters.keys());
  +
  +    }
  +
  +
  +    /**
  +     * Return the defined values for the specified request parameter, if any;
  +     * otherwise, return <code>null</code>.
  +     *
  +     * @param name Name of the desired request parameter
  +     */
  +    public String[] getParameterValues(String name) {
  +
  +	parseParameters();
  +	Object value = parameters.get(name);
  +	if (value == null)
  +	    return (null);
  +	else if (value instanceof String) {
  +	    String values[] = new String[1];
  +	    values[0] = (String) value;
  +	    return (values);
  +	} else if (value instanceof String[])
  +	    return ((String[]) value);
  +	else
  +	    return (null);
  +
  +    }
  +
  +
  +    /**
  +     * Return a RequestDispatcher that wraps the resource at the specified
  +     * path, which may be interpreted as relative to the current request path.
  +     *
  +     * @param path Path of the resource to be wrapped
  +     */
  +    public RequestDispatcher getRequestDispatcher(String path) {
  +
  +	// If the path is already context-relative, just pass it through
  +	if (path == null)
  +	    return (null);
  +	else if (path.startsWith("/"))
  +	    return (context.getServletContext().getRequestDispatcher(path));
  +
  +	// Convert a request-relative path to a context-relative one
  +	String relative = getServletPath() + "/../" + path;
  +	// FIXME -- Canonicalize any ".." directory references!
  +	return (context.getServletContext().getRequestDispatcher(relative));
  +
  +    }
   
   
       /**
  
  
  
  1.2       +497 -22   jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/HttpResponseBase.java
  
  Index: HttpResponseBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/HttpResponseBase.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- HttpResponseBase.java	2000/04/14 19:41:50	1.1
  +++ HttpResponseBase.java	2000/04/17 18:39:48	1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/HttpResponseBase.java,v 1.1 2000/04/14 19:41:50 craigmcc Exp $
  - * $Revision: 1.1 $
  - * $Date: 2000/04/14 19:41:50 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/HttpResponseBase.java,v 1.2 2000/04/17 18:39:48 craigmcc Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/04/17 18:39:48 $
    *
    * ====================================================================
    *
  @@ -66,12 +66,23 @@
   
   
   import java.io.IOException;
  +import java.io.OutputStreamWriter;
  +import java.io.PrintWriter;
  +import java.net.MalformedURLException;
  +import java.net.URL;
  +import java.text.SimpleDateFormat;
  +import java.util.Date;
   import java.util.Enumeration;
   import java.util.Hashtable;
  +import java.util.TimeZone;
   import java.util.Vector;
   import javax.servlet.http.Cookie;
  +import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
  +import javax.servlet.http.HttpSession;
  +import javax.servlet.http.HttpUtils;
   import org.apache.tomcat.HttpResponse;
  +import org.apache.tomcat.util.RequestUtil;
   
   
   /**
  @@ -81,7 +92,7 @@
    * methods need to be implemented.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.1 $ $Date: 2000/04/14 19:41:50 $
  + * @version $Revision: 1.2 $ $Date: 2000/04/17 18:39:48 $
    */
   
   public class HttpResponseBase
  @@ -93,6 +104,22 @@
   
   
       /**
  +     * The set of Cookies associated with this Response.
  +     */
  +    protected Vector cookies = new Vector();
  +
  +
  +    /**
  +     * The date format we will use for creating date headers.
  +     */
  +    protected static final SimpleDateFormat format =
  +	new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
  +    static {
  +	format.setTimeZone(TimeZone.getTimeZone("GMT"));
  +    };
  +
  +
  +    /**
        * The HTTP headers explicitly added via addHeader(), but not including
        * those to be added with setContentLength(), setContentType(), and so on.
        * This collection is keyed by the header name, and the elements are
  @@ -109,11 +136,23 @@
   
   
       /**
  +     * The error message set by <code>sendError()</code>.
  +     */
  +    protected String message = null;
  +
  +
  +    /**
        * The HTTP status code associated with this Response.
        */
       protected int status = HttpServletResponse.SC_OK;
   
   
  +    /**
  +     * The time zone with which to construct date headers.
  +     */
  +    protected static final TimeZone zone = TimeZone.getTimeZone("GMT");
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
  @@ -166,6 +205,17 @@
   
   
       /**
  +     * Return the error message that was set with <code>sendError()</code>
  +     * for this Response.
  +     */
  +    public String getMessage() {
  +
  +	return (this.message);
  +
  +    }
  +
  +
  +    /**
        * Return the HTTP status code associated with this Response.
        */
       public int getStatus() {
  @@ -182,12 +232,378 @@
       public void recycle() {
   
   	super.recycle();
  +	cookies.removeAllElements();
  +	headers.clear();
  +	message = null;
  +	status = HttpServletResponse.SC_OK;
  +
  +    }
  +
  +
  +    // ------------------------------------------------------ Protected Methods
  +
  +
  +    /**
  +     * Return the valid session with which our current request is associated,
  +     * if there is one; otherwise, return <code>null</code.
  +     */
  +    protected HttpSession getSession() {
  +
  +	HttpSession session =
  +	    ((HttpServletRequest) request.getRequest()).getSession(false);
  +	if (session == null)
  +	    return (null);
  +	try {
  +	    session.getCreationTime();	// Validity test
  +	} catch (IllegalStateException e) {
  +	    session = null;
  +	}
  +	return (session);
  +
  +    }
  +
  +
  +    /**
  +     * Returns a default status message for the specified HTTP status code.
  +     *
  +     * @param status The status code for which a message is desired
  +     */
  +    protected String getStatusMessage(int status) {
  +
  +	switch (status) {
  +	case SC_OK:
  +	    return ("OK");
  +	case SC_ACCEPTED:
  +	    return ("Accepted");
  +	case SC_BAD_GATEWAY:
  +	    return ("Bad Gateway");
  +	case SC_BAD_REQUEST:
  +	    return ("Bad Request");
  +	case SC_CONFLICT:
  +	    return ("Conflict");
  +	case SC_CONTINUE:
  +	    return ("Continue");
  +	case SC_CREATED:
  +	    return ("Created");
  +	case SC_EXPECTATION_FAILED:
  +	    return ("Expectation Failed");
  +	case SC_FORBIDDEN:
  +	    return ("Forbidden");
  +	case SC_GATEWAY_TIMEOUT:
  +	    return ("Gateway Timeout");
  +	case SC_GONE:
  +	    return ("Gone");
  +	case SC_HTTP_VERSION_NOT_SUPPORTED:
  +	    return ("HTTP Version Not Supported");
  +	case SC_INTERNAL_SERVER_ERROR:
  +	    return ("Internal Server Error");
  +	case SC_LENGTH_REQUIRED:
  +	    return ("Length Required");
  +	case SC_METHOD_NOT_ALLOWED:
  +	    return ("Method Not Allowed");
  +	case SC_MOVED_PERMANENTLY:
  +	    return ("Moved Permanently");
  +	case SC_MOVED_TEMPORARILY:
  +	    return ("Moved Temporarily");
  +	case SC_MULTIPLE_CHOICES:
  +	    return ("Multiple Choices");
  +	case SC_NO_CONTENT:
  +	    return ("No Content");
  +	case SC_NON_AUTHORITATIVE_INFORMATION:
  +	    return ("Non-Authoritative Information");
  +	case SC_NOT_ACCEPTABLE:
  +	    return ("Not Acceptable");
  +	case SC_NOT_FOUND:
  +	    return ("Not Found");
  +	case SC_NOT_IMPLEMENTED:
  +	    return ("Not Implemented");
  +	case SC_NOT_MODIFIED:
  +	    return ("Not Modified");
  +	case SC_PARTIAL_CONTENT:
  +	    return ("Partial Content");
  +	case SC_PAYMENT_REQUIRED:
  +	    return ("Payment Required");
  +	case SC_PRECONDITION_FAILED:
  +	    return ("Precondition Failed");
  +	case SC_PROXY_AUTHENTICATION_REQUIRED:
  +	    return ("Proxy Authentication Required");
  +	case SC_REQUEST_ENTITY_TOO_LARGE:
  +	    return ("Request Entity Too Large");
  +	case SC_REQUEST_TIMEOUT:
  +	    return ("Request Timeout");
  +	case SC_REQUEST_URI_TOO_LONG:
  +	    return ("Request URI Too Long");
  +	case SC_REQUESTED_RANGE_NOT_SATISFIABLE:
  +	    return ("Requested Range Not Satisfiable");
  +	case SC_RESET_CONTENT:
  +	    return ("Reset Content");
  +	case SC_SEE_OTHER:
  +	    return ("See Other");
  +	case SC_SERVICE_UNAVAILABLE:
  +	    return ("Service Unavailable");
  +	case SC_SWITCHING_PROTOCOLS:
  +	    return ("Switching Protocols");
  +	case SC_UNAUTHORIZED:
  +	    return ("Unauthorized");
  +	case SC_UNSUPPORTED_MEDIA_TYPE:
  +	    return ("Unsupported Media Type");
  +	case SC_USE_PROXY:
  +	    return ("Use Proxy");
  +	default:
  +	    return ("HTTP Response Status " + status);
  +	}
  +
  +    }
  +
  +
  +    /**
  +     * Return <code>true</code> if the specified URL should be encoded with
  +     * a session identifier.  This will be true if all of the following
  +     * conditions are met:
  +     * <ul>
  +     * <li>The request we are responding to asked for a valid session
  +     * <li>The requested session ID was not received via a cookie
  +     * <li>The specified URL points back to somewhere within the web
  +     *     application that is responding to this request
  +     * </ul>
  +     *
  +     * @param location Absolute URL to be validated
  +     **/
  +    private boolean isEncodeable(String location) {
  +
  +	// Are we in a valid session that is not using cookies?
  +	HttpSession session = getSession();
  +	if (session == null)
  +	    return (false);
  +	HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
  +	if (hreq.isRequestedSessionIdFromCookie())
  +	    return (false);
  +
  +	// Is this a valid absolute URL?
  +	URL url = null;
  +	try {
  +	    url = new URL(location);
  +	} catch (MalformedURLException e) {
  +	    return (false);
  +	}
  +
  +	// Does this URL match down to (and including) the context path?
  +	if (!hreq.getScheme().equalsIgnoreCase(url.getProtocol()))
  +	    return (false);
  +	if (!hreq.getServerName().equalsIgnoreCase(url.getHost()))
  +	    return (false);
  +	if (hreq.getServerPort() != url.getPort())
  +	    return (false);
  +	String contextPath = getContext().getPath();
  +	if ((contextPath != null) && (contextPath.length() > 0)) {
  +	    String file = url.getFile();
  +	    if ((file == null) || !file.startsWith(contextPath))
  +		return (false);
  +	}
  +
  +	// This URL belongs to our web application, so it is encodeable
  +	return (true);
  +
  +    }
  +
  +
  +    /**
  +     * Send the HTTP response headers, if this has not already occurred.
  +     */
  +    protected void sendHeaders() throws IOException {
  +
  +	if (isCommitted())
  +	    return;
  +
  +	// Prepare a suitable output stream
  +	OutputStreamWriter osr = null;
  +	    new OutputStreamWriter(getStream(), getCharacterEncoding());
  +	PrintWriter outputWriter = new PrintWriter(osr);
  +
  +	// Send the "Status:" header
  +	outputWriter.print(request.getRequest().getProtocol());
  +	outputWriter.print(status);
  +	if (message != null) {
  +	    outputWriter.print(" ");
  +	    outputWriter.print(message);
  +	    outputWriter.print("\r\n");
  +	}
  +
  +	// Send all specified headers (if any)
  +	Enumeration names = headers.keys();
  +	while (names.hasMoreElements()) {
  +	    String name = (String) names.nextElement();
  +	    Vector values = (Vector) headers.get(name);
  +	    Enumeration items = values.elements();
  +	    while (items.hasMoreElements()) {
  +		String value = (String) items.nextElement();
  +		outputWriter.print(name);
  +		outputWriter.print(": ");
  +		outputWriter.print(value);
  +		outputWriter.print("\r\n");
  +	    }
  +	}
  +
  +	// Add the session ID cookie if necessary
  +	HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
  +	HttpSession session = getSession();
  +	if ((session != null) &&
  +            (session.isNew() || hreq.isRequestedSessionIdFromCookie())) {
  +	    Cookie cookie = new Cookie(Constants.SessionCookie,
  +				       session.getId());
  +	    cookie.setDomain(hreq.getServerName());
  +	    cookie.setMaxAge(-1);
  +	    String contextPath = context.getPath();
  +	    if ((contextPath != null) && (contextPath.length() > 0))
  +		cookie.setPath(contextPath);
  +	    if (hreq.isSecure())
  +		cookie.setSecure(true);
  +	    addCookie(cookie);
  +	}
  +
  +	// Send all specified cookies (if any)
  +	Enumeration items = cookies.elements();
  +	while (items.hasMoreElements()) {
  +	    Cookie cookie = (Cookie) items.nextElement();
  +	    outputWriter.print("Set-Cookie: ");
  +	    outputWriter.print(RequestUtil.encodeCookie(cookie));
  +	    outputWriter.print("\r\n");
  +	}
  +
  +	// Send a terminating blank line to mark the end of the headers
  +	outputWriter.print("\r\n");
  +	outputWriter.flush();
  +
  +    }
  +
  +
  +    /**
  +     * Convert (if necessary) and return the absolute URL that represents the
  +     * resource referenced by this possibly relative URL.  If this URL is
  +     * already absolute, return it unchanged.
  +     *
  +     * @param location URL to be (possibly) converted and then returned
  +     */
  +    private String toAbsolute(String location) {
  +
  +	if (location == null)
  +	    return (location);
  +
  +	// Construct a new absolute URL if possible (cribbed from
  +	// the DefaultErrorPage servlet)
  +	URL url = null;
  +	try {
  +	    url = new URL(location);
  +	} catch (MalformedURLException e1) {
  +	    HttpServletRequest hreq =
  +		(HttpServletRequest) request.getRequest();
  +	    String requrl = HttpUtils.getRequestURL(hreq).toString();
  +	    try {
  +		url = new URL(new URL(requrl), location);
  +	    } catch (MalformedURLException e2) {
  +		return (location);	// Give up
  +	    }
  +	}
  +	return (url.toString());
  +			     
  +    }
  +
  +
  +    /**
  +     * Return the specified URL with the specified session identifier
  +     * suitably encoded.
  +     *
  +     * @param url URL to be encoded with the session id
  +     * @param sessionId Session id to be included in the encoded URL
  +     */
  +    private String toEncoded(String url, String sessionId) {
  +
  +	if ((url == null) || (sessionId == null))
  +	    return (url);
  +
  +	String path = url;
  +	String query = "";
  +	int question = url.indexOf("?");
  +	if (question >= 0) {
  +	    path = url.substring(0, question);
  +	    query = url.substring(question);
  +	}
  +	StringBuffer sb = new StringBuffer(path);
  +	sb.append(";jsessionid=");
  +	sb.append(sessionId);
  +	sb.append(query);
  +	return (sb.toString());
  +
  +    }
  +
  +
  +    // ------------------------------------------------ ServletResponse Methods
  +
  +
  +    /**
  +     * Flush the buffer and commit this response.  If this is the first output,
  +     * send the HTTP headers prior to the user data.
  +     *
  +     * @exception IOException if an input/output error occurs
  +     */
  +    public void flushBuffer() throws IOException {
  +
  +	if (!isCommitted())
  +	    sendHeaders();
  +
  +	super.flushBuffer();
  +
  +    }
  +
  +
  +    /**
  +     * Clear any content written to the buffer.
  +     *
  +     * @exception IllegalStateException if this response has already
  +     *  been committed
  +     */
  +    public void reset() {
  +
  +	super.reset();
  +	cookies.removeAllElements();
   	headers.clear();
  -	status = -1;
  +	message = null;
  +	status = HttpServletResponse.SC_OK;
  +
  +    }
  +
   
  +    /**
  +     * Set the content length (in bytes) for this Response.
  +     *
  +     * @param length The new content length
  +     */
  +    public void setContentLength(int length) {
  +
  +	if (isCommitted())
  +	    return;
  +	super.setContentLength(length);
  +	setIntHeader("Content-Length", length);
  +
       }
   
   
  +
  +    /**
  +     * Set the content type for this Response.
  +     *
  +     * @param type The new content type
  +     */
  +    public void setContentType(String type) {
  +
  +	if (isCommitted())
  +	    return;
  +	super.setContentType(type);
  +	setHeader("Content-Type", type);
  +
  +    }
  +
  +
       // -------------------------------------------- HttpServletResponse Methods
   
   
  @@ -199,7 +615,10 @@
        */
       public void addCookie(Cookie cookie) {
   
  -	;	// FIXME: addCookie()
  +	if (isCommitted())
  +	    return;
  +	if (cookie != null)
  +	    cookies.addElement(cookie);
   
       }
   
  @@ -212,7 +631,9 @@
        */
       public void addDateHeader(String name, long value) {
   
  -	;	// FIXME: setDateHeader()
  +	if (isCommitted())
  +	    return;
  +	addHeader(name, format.format(new Date(value)));
   
       }
   
  @@ -225,7 +646,16 @@
        */
       public void addHeader(String name, String value) {
   
  -	;	// FIXME: addHeader()
  +	if (isCommitted())
  +	    return;
  +	Vector values = (Vector) headers.get(name);
  +	if (values != null)
  +	    values.addElement(value);
  +	else {
  +	    values = new Vector();
  +	    values.addElement(value);
  +	    headers.put(name, values);
  +	}
   
       }
   
  @@ -238,7 +668,9 @@
        */
       public void addIntHeader(String name, int value) {
   
  -	;	// FIXME: addIntHeader()
  +	if (isCommitted())
  +	    return;
  +	addHeader(name, "" + value);
   
       }
   
  @@ -250,7 +682,7 @@
        */
       public boolean containsHeader(String name) {
   
  -	return (false);	// FIXME: containsHeader
  +	return (headers.get(name) != null);
   
       }
   
  @@ -263,7 +695,10 @@
        */
       public String encodeRedirectURL(String url) {
   
  -	return (url);	// FIXME: encodeRedirectURL()
  +	if (isEncodeable(toAbsolute(url)))
  +	    return (toEncoded(url, getSession().getId()));
  +	else
  +	    return (url);
   
       }
   
  @@ -292,7 +727,10 @@
        */
       public String encodeURL(String url) {
   
  -	return (url);	// FIXME: encodeURL()
  +	if (isEncodeable(toAbsolute(url)))
  +	    return (toEncoded(url, getSession().getId()));
  +	else
  +	    return (url);
   
       }
   
  @@ -325,7 +763,7 @@
        */
       public void sendError(int status) throws IOException {
   
  -	;	// FIXME: sendError(status)
  +	sendError(status, getStatusMessage(status));
   
       }
   
  @@ -342,7 +780,28 @@
        */
       public void sendError(int status, String message) throws IOException {
   
  -	;	// FIXME: sendError(status, message)
  +	if (isCommitted())
  +	    throw new IllegalStateException
  +		(sm.getString("httpResponseBase.sendError.ise"));
  +
  +
  +	// Format a default output message for this error
  +	reset();
  +	setContentType("text/html");
  +	this.status = status;
  +	this.message = message;
  +	flushBuffer();
  +
  +	PrintWriter outputWriter = getWriter();
  +	outputWriter.print("<html>\r\n");
  +	outputWriter.print("<head>\r\n");
  +	outputWriter.print("<title>Tomcat Error Report</title>\r\n");
  +	outputWriter.print("</head>\r\n");
  +	outputWriter.print("<body bgcolor=\"white\">\r\n");
  +	outputWriter.print(message);
  +	outputWriter.print("</body>\r\n");
  +	outputWriter.print("</html>\r\n");
  +	outputWriter.flush();
   
       }
   
  @@ -358,7 +817,14 @@
        */
       public void sendRedirect(String location) throws IOException {
   
  -	;	// FIXME: sendRedirect()
  +	if (isCommitted())
  +	    throw new IllegalStateException
  +		(sm.getString("httpResponseBase.sendRedirect.ise"));
  +
  +	reset();
  +	setStatus(SC_MOVED_TEMPORARILY, location);
  +	setHeader("Location", location);
  +	flushBuffer();
   
       }
   
  @@ -367,11 +833,13 @@
        * Set the specified date header to the specified value.
        *
        * @param name Name of the header to set
  -     * @param date Date value to be set
  +     * @param value Date value to be set
        */
  -    public void setDateHeader(String name, long date) {
  +    public void setDateHeader(String name, long value) {
   
  -	;	// FIXME: setDateHeader()
  +	if (isCommitted())
  +	    return;
  +	setHeader(name, format.format(new Date(value)));
   
       }
   
  @@ -384,7 +852,11 @@
        */
       public void setHeader(String name, String value) {
   
  -	;	// FIXME: setHeader()
  +	if (isCommitted())
  +	    return;
  +	Vector values = new Vector();
  +	values.addElement(value);
  +	headers.put(name, values);
   
       }
   
  @@ -397,7 +869,9 @@
        */
       public void setIntHeader(String name, int value) {
   
  -	;	// FIXME: setIntHeader()
  +	if (isCommitted())
  +	    return;
  +	setHeader(name, "" + value);
   
       }
   
  @@ -409,7 +883,7 @@
        */
       public void setStatus(int status) {
   
  -	;	// FIXME: setStatus(status)
  +	setStatus(status, getStatusMessage(status));
   
       }
   
  @@ -426,7 +900,8 @@
        */
       public void setStatus(int status, String message) {
   
  -	;	// FIXME: setStatus(status, message)
  +	this.status = status;
  +	this.message = message;
   
       }
   
  
  
  
  1.2       +6 -0      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/LocalStrings.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LocalStrings.properties	2000/04/15 23:36:15	1.1
  +++ LocalStrings.properties	2000/04/17 18:39:48	1.2
  @@ -1,4 +1,10 @@
  +httpResponseBase.sendError.ise=Cannot call sendError() after the response has been committed
  +httpResponseBase.sendRedirect.ise=Cannot call sendRedirect() after the response has been committed
   requestBase.getInputStream.ise=getReader() has already been called for this request
   requestBase.getReader.ise=getInputStream() has already been called for this request
   requestStream.close.closed=Cannot close the same input stream twice
   requestStream.read.closed=This input stream has been closed
  +response.getOutputStream.ise=getWriter() has already been called for this response
  +response.getWriter.ise=getOutputStream() has already been called for this response
  +responseBase.reset.ise=Cannot reset after response has been committed
  +responseBase.setBufferSize.ise=Buffer size cannot be changed after data has been written
  
  
  
  1.6       +5 -6      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/RequestBase.java
  
  Index: RequestBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/RequestBase.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- RequestBase.java	2000/04/16 05:13:36	1.5
  +++ RequestBase.java	2000/04/17 18:39:48	1.6
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/RequestBase.java,v 1.5 2000/04/16 05:13:36 craigmcc Exp $
  - * $Revision: 1.5 $
  - * $Date: 2000/04/16 05:13:36 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/RequestBase.java,v 1.6 2000/04/17 18:39:48 craigmcc Exp $
  + * $Revision: 1.6 $
  + * $Date: 2000/04/17 18:39:48 $
    *
    * ====================================================================
    *
  @@ -90,11 +90,10 @@
   /**
    * Convenience base implementation of the <b>Request</b> interface, which can
    * be used for the Request implementation required by most Connectors.  Only
  - * the connector-specific methods need to be implemented, which are marked
  - * abstract in this class.
  + * the connector-specific methods need to be implemented.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.5 $ $Date: 2000/04/16 05:13:36 $
  + * @version $Revision: 1.6 $ $Date: 2000/04/17 18:39:48 $
    */
   
   public abstract class RequestBase
  
  
  
  1.4       +113 -33   jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/ResponseBase.java
  
  Index: ResponseBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/ResponseBase.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ResponseBase.java	2000/04/14 19:41:50	1.3
  +++ ResponseBase.java	2000/04/17 18:39:48	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/ResponseBase.java,v 1.3 2000/04/14 19:41:50 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/04/14 19:41:50 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/ResponseBase.java,v 1.4 2000/04/17 18:39:48 craigmcc Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/04/17 18:39:48 $
    *
    * ====================================================================
    *
  @@ -67,6 +67,7 @@
   
   import java.io.IOException;
   import java.io.OutputStream;
  +import java.io.OutputStreamWriter;
   import java.io.PrintWriter;
   import java.util.Locale;
   import javax.servlet.ServletException;
  @@ -76,6 +77,8 @@
   import org.apache.tomcat.Context;
   import org.apache.tomcat.Request;
   import org.apache.tomcat.Response;
  +import org.apache.tomcat.util.RequestUtil;
  +import org.apache.tomcat.util.StringManager;
   
   
   /**
  @@ -84,10 +87,10 @@
    * the connector-specific methods need to be implemented.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.3 $ $Date: 2000/04/14 19:41:50 $
  + * @version $Revision: 1.4 $ $Date: 2000/04/17 18:39:48 $
    */
   
  -public class ResponseBase
  +public abstract class ResponseBase
       implements Response, ServletResponse {
   
   
  @@ -95,6 +98,24 @@
   
   
       /**
  +     * The buffer through which all of our output bytes are passed.
  +     */
  +    protected byte[] buffer = new byte[1];
  +
  +
  +    /**
  +     * The number of data bytes currently in the buffer.
  +     */
  +    protected int bufferCount = 0;
  +
  +
  +    /**
  +     * Has this response been committed yet?
  +     */
  +    protected boolean committed = false;
  +
  +
  +    /**
        * The Connector through which this Response is returned.
        */
       protected Connector connector = null;
  @@ -126,17 +147,44 @@
   
   
       /**
  +     * The Locale associated with this Response.
  +     */
  +    protected Locale locale = null;
  +
  +
  +    /**
  +     * The output stream associated with this Response.
  +     */
  +    protected OutputStream output = null;
  +
  +
  +    /**
        * The Request with which this Response is associated.
        */
       protected Request request = null;
   
   
       /**
  -     * The output stream associated with this Response.
  +     * The string manager for this package.
        */
  -    protected OutputStream stream = null;
  +    protected static StringManager sm =
  +	StringManager.getManager(Constants.Package);
   
   
  +    /**
  +     * The ServletOutputStream that has been returned by
  +     * <code>getOutputStream()</code>, if any.
  +     */
  +    protected ServletOutputStream stream = null;
  +
  +
  +    /**
  +     * The PrintWriter that has been returned by
  +     * <code>getWriter()</code>, if any.
  +     */
  +    protected PrintWriter writer = null;
  +
  +
       // ------------------------------------------------------------- Properties
   
   
  @@ -235,7 +283,7 @@
        */
       public OutputStream getStream() {
   
  -	return (this.stream);
  +	return (this.output);
   
       }
   
  @@ -247,7 +295,7 @@
        */
       public void setStream(OutputStream stream) {
   
  -	this.stream = stream;
  +	this.output = stream;
   
       }
   
  @@ -269,20 +317,6 @@
   
   
       /**
  -     * Ensure that the HTTP headers (and any buffered output) have been
  -     * flushed to the output stream, even if it was never acquired by
  -     * a servlet.
  -     *
  -     * @exception IOException if an input/output error occurs
  -     */
  -    public void flush() throws IOException {
  -
  -	// FIXME: flush()
  -
  -    }
  -
  -
  -    /**
        * Return the content length that was set or calculated for this Response.
        */
       public int getContentLength() {
  @@ -309,12 +343,18 @@
        */
       public void recycle() {
   
  +	// buffer is NOT reset when recycling
  +	bufferCount = 0;
  +	committed = false;
   	// connector is NOT reset when recycling
   	contentLength = -1;
   	contentType = "text/plain";
   	context = null;
  +	locale = null;
  +	output = null;
   	request = null;
   	stream = null;
  +	writer = null;
   
       }
   
  @@ -329,7 +369,11 @@
        */
       public void flushBuffer() throws IOException {
   
  -	;	// FIXME: flushBuffer()
  +	committed = true;
  +	if (bufferCount > 0) {
  +	    output.write(buffer, 0, bufferCount);
  +	    bufferCount = 0;
  +	}
   
       }
   
  @@ -339,7 +383,7 @@
        */
       public int getBufferSize() {
   
  -	return (-1);	// FIXME: getBufferSize()
  +	return (buffer.length);
   
       }
   
  @@ -349,7 +393,7 @@
        */
       public String getCharacterEncoding() {
   
  -	return (null);	// FIXME: getCharacterEncoding()
  +	return (RequestUtil.parseCharacterEncoding(getContentType()));
   
       }
   
  @@ -363,7 +407,13 @@
        */
       public ServletOutputStream getOutputStream() throws IOException {
   
  -	return (null);	// FIXME: getOutputStream()
  +	if (writer != null)
  +	    throw new IllegalStateException
  +		(sm.getString("responseBase.getOutputStream.ise"));
  +
  +	if (stream != null)
  +	    stream = createOutputStream();
  +	return (stream);
   
       }
   
  @@ -373,7 +423,7 @@
        */
       public Locale getLocale() {
   
  -	return (null);
  +	return (locale);
   
       }
   
  @@ -387,7 +437,17 @@
        */
       public PrintWriter getWriter() throws IOException {
   
  -	return (null);	// FIXME: getWriter()
  +	if (stream != null)
  +	    throw new IllegalStateException
  +		(sm.getString("responseBase.getWriter.ise"));
  +
  +	if (writer == null) {
  +	    OutputStreamWriter osr =
  +		new OutputStreamWriter(createOutputStream(),
  +				       getCharacterEncoding());
  +	    writer = new PrintWriter(osr);
  +	}
  +	return (writer);
   
       }
   
  @@ -397,7 +457,7 @@
        */
       public boolean isCommitted() {
   
  -	return (false);	// FIXME: isCommitted()
  +	return (committed);
   
       }
   
  @@ -409,8 +469,16 @@
        *  been committed
        */
       public void reset() {
  +
  +	if (committed)
  +	    throw new IllegalStateException
  +		(sm.getString("responseBase.reset.ise"));
   
  -	;	// FIXME: reset()
  +	bufferCount = 0;
  +	contentLength = -1;
  +	contentType = "text/plain";
  +	stream = null;
  +	writer = null;
   
       }
   
  @@ -425,7 +493,13 @@
        */
       public void setBufferSize(int size) {
   
  -	;	// FIXME: setBufferSize()
  +	if (bufferCount > 0)
  +	    throw new IllegalStateException
  +		(sm.getString("responseBase.setBufferSize.ise"));
  +
  +	if (buffer.length >= size)
  +	    return;
  +	buffer = new byte[size];
   
       }
   
  @@ -437,6 +511,8 @@
        */
       public void setContentLength(int length) {
   
  +	if (isCommitted())
  +	    return;
   	this.contentLength = length;
   
       }
  @@ -449,6 +525,8 @@
        */
       public void setContentType(String type) {
   
  +	if (isCommitted())
  +	    return;
   	this.contentType = type;
   
       }
  @@ -462,7 +540,9 @@
        */
       public void setLocale(Locale locale) {
   
  -	;	// FIXME: setLocale()
  +	if (isCommitted())
  +	    return;
  +	this.locale = locale;
   
       }
   
  
  
  
  1.4       +3 -5      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/Constants.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Constants.java	2000/04/16 05:13:37	1.3
  +++ Constants.java	2000/04/17 18:39:49	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/Constants.java,v 1.3 2000/04/16 05:13:37 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/04/16 05:13:37 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/Constants.java,v 1.4 2000/04/17 18:39:49 craigmcc Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/04/17 18:39:49 $
    *
    * ====================================================================
    *
  @@ -74,7 +74,5 @@
       public static final String Package = "org.apache.tomcat.connector.http";
       public static final String ServerInfo =
   	"Tomcat (Catalina)/0.1";
  -    public static final String SessionCookie = "JSESSIONID";
  -    public static final String SessionParameter = "jsessionid";
   
   }
  
  
  
  1.7       +7 -6      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpProcessor.java
  
  Index: HttpProcessor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpProcessor.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- HttpProcessor.java	2000/04/17 00:52:17	1.6
  +++ HttpProcessor.java	2000/04/17 18:39:49	1.7
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpProcessor.java,v 1.6 2000/04/17 00:52:17 craigmcc Exp $
  - * $Revision: 1.6 $
  - * $Date: 2000/04/17 00:52:17 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpProcessor.java,v 1.7 2000/04/17 18:39:49 craigmcc Exp $
  + * $Revision: 1.7 $
  + * $Date: 2000/04/17 18:39:49 $
    *
    * ====================================================================
    *
  @@ -97,7 +97,7 @@
    * the request.  When the processor is completed, it will recycle itself.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.6 $ $Date: 2000/04/17 00:52:17 $
  + * @version $Revision: 1.7 $ $Date: 2000/04/17 18:39:49 $
    */
   
   final class HttpProcessor
  @@ -154,7 +154,7 @@
        * The match string for identifying a session ID parameter.
        */
       private static final String match =
  -	";" + Constants.SessionParameter + "=";
  +	";" + org.apache.tomcat.connector.Constants.SessionParameter + "=";
   
   
       /**
  @@ -317,7 +317,8 @@
   	    } else if (match.equals("cookie")) {
   		Cookie cookies[] = RequestUtil.parseCookieHeader(value);
   		for (int i = 0; i < cookies.length; i++) {
  -		    if (cookies[i].getName().equals(Constants.SessionCookie)) {
  +		    if (cookies[i].getName().equals
  +			(org.apache.tomcat.connector.Constants.SessionCookie)) {
   			// Override anything requested in the URL
   			request.setRequestedSessionId(cookies[i].getValue());
   			request.setRequestedSessionCookie(true);
  
  
  
  1.4       +4 -88     jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpRequestImpl.java
  
  Index: HttpRequestImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpRequestImpl.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- HttpRequestImpl.java	2000/04/15 23:36:16	1.3
  +++ HttpRequestImpl.java	2000/04/17 18:39:49	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpRequestImpl.java,v 1.3 2000/04/15 23:36:16 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/04/15 23:36:16 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpRequestImpl.java,v 1.4 2000/04/17 18:39:49 craigmcc Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/04/17 18:39:49 $
    *
    * ====================================================================
    *
  @@ -65,21 +65,15 @@
   package org.apache.tomcat.connector.http;
   
   
  -import java.io.BufferedReader;
  -import java.io.IOException;
   import java.net.InetAddress;
  -import java.util.Enumeration;
  -import javax.servlet.RequestDispatcher;
  -import javax.servlet.ServletInputStream;
   import org.apache.tomcat.connector.HttpRequestBase;
  -import org.apache.tomcat.connector.RequestStream;
   
   
   /**
    * Implementation of <b>HttpRequest</b> specific to the HTTP connector.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.3 $ $Date: 2000/04/15 23:36:16 $
  + * @version $Revision: 1.4 $ $Date: 2000/04/17 18:39:49 $
    */
   
   final class HttpRequestImpl
  @@ -161,71 +155,6 @@
   
   
       /**
  -     * Return the servlet input stream for this Request.
  -     *
  -     * @exception IllegalStateException if <code>getReader()</code> has
  -     *  already been called for this request
  -     * @exception IOException if an input/output error occurs
  -     */
  -    public ServletInputStream getInputStream() throws IOException {
  -
  -	return (null);	// FIXME: getInputStream()
  -
  -    }
  -
  -
  -    /**
  -     * Return the value of the specified request parameter, if any; otherwise,
  -     * return <code>null</code>.  If there is more than one value defined,
  -     * return only the first one.
  -     *
  -     * @param name Name of the desired request parameter
  -     */
  -    public String getParameter(String name) {
  -
  -	return (null);	// FIXME: getParameter()
  -
  -    }
  -
  -
  -    /**
  -     * Return the names of all defined request parameters for this request.
  -     */
  -    public Enumeration getParameterNames() {
  -
  -	return (null);	// FIXME: getParameterNames()
  -
  -    }
  -
  -
  -    /**
  -     * Return the defined values for the specified request parameter, if any;
  -     * otherwise, return <code>null</code>.
  -     *
  -     * @param name Name of the desired request parameter
  -     */
  -    public String[] getParameterValues(String name) {
  -
  -	return (null);	// FIXME: getParameterValues()
  -
  -    }
  -
  -
  -    /**
  -     * Read the Reader wrapping the input stream for this Request.
  -     *
  -     * @exception IllegalStateException if <code>getInputStream()</code>
  -     *  has already been called for this request
  -     * @exception IOException if an input/output error occurs
  -     */
  -    public BufferedReader getReader() {
  -
  -	return (null);	// FIXME: getReader()
  -
  -    }
  -
  -
  -    /**
        * Return the Internet Protocol (IP) address of the client that sent
        * this request.
        */
  @@ -243,19 +172,6 @@
       public String getRemoteHost() {
   
   	return (inet.getHostName());
  -
  -    }
  -
  -
  -    /**
  -     * Return a RequestDispatcher that wraps the resource at the specified
  -     * path, which may be interpreted as relative to the current request path.
  -     *
  -     * @param path Path of the resource to be wrapped
  -     */
  -    public RequestDispatcher getRequestDispatcher(String path) {
  -
  -	return (null);	// FIXME: getRequestDispatcher()
   
       }
   
  
  
  
  1.6       +5 -5      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/security/HttpBasicAuth.java
  
  Index: HttpBasicAuth.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/security/HttpBasicAuth.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- HttpBasicAuth.java	2000/04/14 19:41:53	1.5
  +++ HttpBasicAuth.java	2000/04/17 18:39:49	1.6
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/security/HttpBasicAuth.java,v 1.5 2000/04/14 19:41:53 craigmcc Exp $
  - * $Revision: 1.5 $
  - * $Date: 2000/04/14 19:41:53 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/security/HttpBasicAuth.java,v 1.6 2000/04/17 18:39:49 craigmcc Exp $
  + * $Revision: 1.6 $
  + * $Date: 2000/04/17 18:39:49 $
    *
    * ====================================================================
    *
  @@ -85,7 +85,7 @@
    * if this is not the case.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.5 $ $Date: 2000/04/14 19:41:53 $
  + * @version $Revision: 1.6 $ $Date: 2000/04/17 18:39:49 $
    */
   
   final class HttpBasicAuth {
  @@ -133,7 +133,7 @@
   		request.getRequest().getServerPort();
   	hres.setHeader("WWW-Authenticate", "Basic \"" + realmName + "\"");
   	hres.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
  -	response.flush();
  +	response.getResponse().flushBuffer();
   	return (false);
   
       }
  
  
  
  1.2       +59 -3     jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/util/RequestUtil.java
  
  Index: RequestUtil.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/util/RequestUtil.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- RequestUtil.java	2000/04/15 23:36:17	1.1
  +++ RequestUtil.java	2000/04/17 18:39:50	1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/util/RequestUtil.java,v 1.1 2000/04/15 23:36:17 craigmcc Exp $
  - * $Revision: 1.1 $
  - * $Date: 2000/04/15 23:36:17 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/util/RequestUtil.java,v 1.2 2000/04/17 18:39:50 craigmcc Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/04/17 18:39:50 $
    *
    * ====================================================================
    *
  @@ -65,7 +65,10 @@
   package org.apache.tomcat.util;
   
   
  +import java.text.SimpleDateFormat;
  +import java.util.Date;
   import java.util.StringTokenizer;
  +import java.util.TimeZone;
   import java.util.Vector;
   import javax.servlet.http.Cookie;
   
  @@ -74,10 +77,63 @@
    * General purpose request parsing and encoding utility methods.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.1 $ $Date: 2000/04/15 23:36:17 $
  + * @version $Revision: 1.2 $ $Date: 2000/04/17 18:39:50 $
    */
   
   public final class RequestUtil {
  +
  +
  +    /**
  +     * The DateFormat to use for generating readable dates in cookies.
  +     */
  +    private static SimpleDateFormat format =
  +        new SimpleDateFormat(" EEEE, dd-MMM-yy kk:mm:ss zz");
  +
  +    static {
  +        format.setTimeZone(TimeZone.getTimeZone("GMT"));
  +    }
  +
  +
  +    /**
  +     * Encode a cookie as per the Netscape Cookies specification. The
  +     * resulting string can be used in a Set-Cookie header.
  +     *
  +     * @param cookie The cookie to encode.
  +     * @return A string following Netscape Cookies specification.
  +     */
  +    public static String encodeCookie(Cookie cookie) {
  +
  +        StringBuffer buf = new StringBuffer( cookie.getName() );
  +        buf.append('=');
  +        buf.append(cookie.getValue());
  +
  +        long age = cookie.getMaxAge();
  +        if (age > 0) {
  +            buf.append("; expires=");
  +            buf.append(format.format(
  +                new Date(System.currentTimeMillis() + (long)age * 1000 )));
  +        } else if (age == 0) {
  +            buf.append("; expires=");
  +            // Set expiration to the epoch to delete the cookie
  +            buf.append(format.format(new Date(0)));
  +        }
  +
  +        if (cookie.getDomain() != null) {
  +            buf.append("; domain=");
  +            buf.append(cookie.getDomain());
  +        }
  +
  +        if (cookie.getPath() != null) {
  +            buf.append("; path=");
  +            buf.append(cookie.getPath());
  +        }
  +
  +        if (cookie.getSecure()) {
  +            buf.append("; secure");
  +        }
  +
  +        return (buf.toString());
  +    }
   
   
       /**