markt       2005/05/11 14:39:41

  Modified:    catalina/src/share/org/apache/catalina/authenticator
                        FormAuthenticator.java SavedRequest.java
               webapps/docs changelog.xml
  Log:
  Include request body in saved request when using FORM authentication.
   - Fixes problem with saved request assuming platform default encoding for 
POSTed
    parameters.
   - Improves restoration of request by using CoyoteRequest
  
  Revision  Changes    Path
  1.20      +89 -25    
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java
  
  Index: FormAuthenticator.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- FormAuthenticator.java    31 Mar 2005 10:31:54 -0000      1.19
  +++ FormAuthenticator.java    11 May 2005 21:39:41 -0000      1.20
  @@ -19,11 +19,11 @@
   
   
   import java.io.IOException;
  +import java.io.InputStream;
   import java.security.Principal;
   import java.util.Enumeration;
   import java.util.Iterator;
   import java.util.Locale;
  -import java.util.Map;
   
   import javax.servlet.RequestDispatcher;
   import javax.servlet.http.Cookie;
  @@ -36,11 +36,14 @@
   import org.apache.catalina.deploy.LoginConfig;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  +import org.apache.coyote.InputBuffer;
  +import org.apache.coyote.http11.InputFilter;
  +import org.apache.coyote.http11.InternalInputBuffer;
  +import org.apache.tomcat.util.buf.ByteChunk;
   import org.apache.tomcat.util.buf.CharChunk;
   import org.apache.tomcat.util.buf.MessageBytes;
   
   
  -
   /**
    * An <b>Authenticator</b> and <b>Valve</b> implementation of FORM BASED
    * Authentication, as described in the Servlet API Specification, Version 
2.2.
  @@ -187,7 +190,8 @@
           if (matchRequest(request)) {
               session = request.getSessionInternal(true);
               if (log.isDebugEnabled())
  -                log.debug("Restore request from session '" + 
session.getIdInternal() 
  +                log.debug("Restore request from session '"
  +                          + session.getIdInternal() 
                             + "'");
               principal = (Principal)
                   session.getNote(Constants.FORM_PRINCIPAL_NOTE);
  @@ -273,7 +277,8 @@
               session = request.getSessionInternal(false);
           if (session == null) {
               if (containerLog.isDebugEnabled())
  -                containerLog.debug("User took so long to log on the session 
expired");
  +                containerLog.debug
  +                    ("User took so long to log on the session expired");
               response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT,
                                  sm.getString("authenticator.sessionExpired"));
               return (false);
  @@ -345,7 +350,8 @@
        * @param request The request to be restored
        * @param session The session containing the saved information
        */
  -    protected boolean restoreRequest(Request request, Session session) {
  +    protected boolean restoreRequest(Request request, Session session)
  +        throws IOException {
   
           // Retrieve and remove the SavedRequest object from our session
           SavedRequest saved = (SavedRequest)
  @@ -361,7 +367,8 @@
           while (cookies.hasNext()) {
               request.addCookie((Cookie) cookies.next());
           }
  -        request.clearHeaders();
  +
  +        request.getCoyoteRequest().getMimeHeaders().recycle();
           Iterator names = saved.getHeaderNames();
           while (names.hasNext()) {
               String name = (String) names.next();
  @@ -370,24 +377,39 @@
                   request.addHeader(name, (String) values.next());
               }
           }
  +        
           request.clearLocales();
           Iterator locales = saved.getLocales();
           while (locales.hasNext()) {
               request.addLocale((Locale) locales.next());
           }
  -        request.clearParameters();
  +        
  +        request.getCoyoteRequest().getParameters().recycle();
  +        
           if ("POST".equalsIgnoreCase(saved.getMethod())) {
  -            Iterator paramNames = saved.getParameterNames();
  -            while (paramNames.hasNext()) {
  -                String paramName = (String) paramNames.next();
  -                String paramValues[] =
  -                    saved.getParameterValues(paramName);
  -                request.addParameter(paramName, paramValues);
  -            }
  +            ByteChunk body = saved.getBody();
  +
  +            // Set content length
  +            request.getCoyoteRequest().setContentLength(body.getLength());
  +
  +            // Restore body
  +            InputFilter savedBody = new SavedRequestInputFilter(body);
  +            InternalInputBuffer internalBuffer = (InternalInputBuffer)
  +                request.getCoyoteRequest().getInputBuffer();
  +            internalBuffer.addActiveFilter(savedBody);
  +
  +            // Set content type
  +            MessageBytes contentType = MessageBytes.newInstance();
  +            contentType.setString("application/x-www-form-urlencoded");
  +            request.getCoyoteRequest().setContentType(contentType);
           }
  -        request.setMethod(saved.getMethod());
  -        request.setQueryString(saved.getQueryString());
  -        request.setRequestURI(saved.getRequestURI());
  +        request.getCoyoteRequest().method().setString(saved.getMethod());
  +
  +        request.getCoyoteRequest().queryString().setString
  +            (saved.getQueryString());
  +
  +        request.getCoyoteRequest().requestURI().setString
  +            (saved.getRequestURI());
           return (true);
   
       }
  @@ -398,8 +420,10 @@
        *
        * @param request The request to be saved
        * @param session The session to contain the saved information
  +     * @throws IOException
        */
  -    private void saveRequest(Request request, Session session) {
  +    private void saveRequest(Request request, Session session)
  +        throws IOException {
   
           // Create and populate a SavedRequest object for this request
           SavedRequest saved = new SavedRequest();
  @@ -422,13 +446,22 @@
               Locale locale = (Locale) locales.nextElement();
               saved.addLocale(locale);
           }
  -        Map parameters = request.getParameterMap();
  -        Iterator paramNames = parameters.keySet().iterator();
  -        while (paramNames.hasNext()) {
  -            String paramName = (String) paramNames.next();
  -            String paramValues[] = (String[]) parameters.get(paramName);
  -            saved.addParameter(paramName, paramValues);
  +
  +        if ("POST".equalsIgnoreCase(request.getMethod())) {
  +            // Note that the size of the request body is limited by:
  +            // request.getConnector().getMaxPostSize()
  +
  +            byte[] buffer = new byte[4096];
  +            int bytesRead;
  +            InputStream is = request.getInputStream();
  +            ByteChunk body = new ByteChunk();
  +            
  +            while ( (bytesRead = is.read(buffer) ) >= 0) {
  +                body.append(buffer, 0, bytesRead);
  +            }
  +            saved.setBody(body);
           }
  +
           saved.setMethod(request.getMethod());
           saved.setQueryString(request.getQueryString());
           saved.setRequestURI(request.getRequestURI());
  @@ -460,5 +493,36 @@
   
       }
   
  +    protected class SavedRequestInputFilter implements InputFilter {
  +
  +        protected ByteChunk input = null;
  +
  +        public SavedRequestInputFilter(ByteChunk input) {
  +            this.input = input;
  +        }
  +
  +        public int doRead(ByteChunk chunk, org.apache.coyote.Request request)
  +        throws IOException {
  +            return input.substract(chunk);
  +        }
  +
  +             public void setRequest(org.apache.coyote.Request request) {
  +             }
  +
  +             public void recycle() {
  +            input = null;
  +             }
  +
  +             public ByteChunk getEncodingName() {
  +                     return null;
  +             }
  +
  +             public void setBuffer(InputBuffer buffer) {
  +             }
  +
  +             public long end() throws IOException {
  +                     return 0;
  +             }
  +    }
   
   }
  
  
  
  1.4       +15 -6     
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SavedRequest.java
  
  Index: SavedRequest.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SavedRequest.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SavedRequest.java 27 Feb 2004 14:58:41 -0000      1.3
  +++ SavedRequest.java 11 May 2005 21:39:41 -0000      1.4
  @@ -25,6 +25,8 @@
   
   import javax.servlet.http.Cookie;
   
  +import org.apache.tomcat.util.buf.ByteChunk;
  +
   
   /**
    * Object that saves the critical information from a request so that
  @@ -34,11 +36,6 @@
    * <b>IMPLEMENTATION NOTE</b> - It is assumed that this object is accessed
    * only from the context of a single thread, so no synchronization around
    * internal collection classes is performed.
  - * <p>
  - * <b>FIXME</b> - Currently, this object has no mechanism to save or
  - * restore the data content of the request, although it does save
  - * request parameters so that a POST transaction can be faithfully
  - * duplicated.
    *
    * @author Craig R. McClanahan
    * @version $Revision$ $Date$
  @@ -167,5 +164,17 @@
           this.requestURI = requestURI;
       }
   
  +    
  +    /**
  +     * The body of this request.
  +     */
  +    private ByteChunk body = null;
  +    
  +    public ByteChunk getBody() {
  +        return (this.body);
  +    }
   
  +    public void setBody(ByteChunk body) {
  +        this.body = body;
  +    }
   }
  
  
  
  1.307     +5 -0      jakarta-tomcat-catalina/webapps/docs/changelog.xml
  
  Index: changelog.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/webapps/docs/changelog.xml,v
  retrieving revision 1.306
  retrieving revision 1.307
  diff -u -r1.306 -r1.307
  --- changelog.xml     11 May 2005 21:22:14 -0000      1.306
  +++ changelog.xml     11 May 2005 21:39:41 -0000      1.307
  @@ -148,6 +148,11 @@
         <fix>
           Fix NPE when POST size exceeds limit defined by maxPostSize. (markt)
         </fix>
  +      <fix>
  +        Fix FORM authentication so POSTed parameters are not assumed to be 
encoded with platform
  +        default encoding. A side effect of this fix is that the bodies of 
POST requests that
  +        require FORM authentication are now buffered and made available 
after a sucessful login. (markt)
  +      </fix>
       </changelog>
     </subsection>
     
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to