luehe       2004/10/27 15:58:17

  Modified:    catalina/src/share/org/apache/catalina/core
                        StandardWrapper.java
               catalina/src/share/org/apache/catalina Wrapper.java
               catalina/src/share/org/apache/catalina/connector
                        CoyoteAdapter.java
  Log:
  If TRACE has been disabled, return appropriate error code
  (405, instead of the current 403) and include Allow header in response, in
  order to comply with HTTP 1.1 spec:
  
    10.4.6 405 Method Not Allowed
  
      The method specified in the Request-Line is not allowed for the
      resource identified by the Request-URI. The response MUST include an
      Allow header containing a list of valid methods for the requested
      resource.
  
  Revision  Changes    Path
  1.54      +69 -2     
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardWrapper.java
  
  Index: StandardWrapper.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardWrapper.java,v
  retrieving revision 1.53
  retrieving revision 1.54
  diff -u -r1.53 -r1.54
  --- StandardWrapper.java      26 Oct 2004 21:55:43 -0000      1.53
  +++ StandardWrapper.java      27 Oct 2004 22:58:17 -0000      1.54
  @@ -17,11 +17,12 @@
   
   package org.apache.catalina.core;
   
  -
  +import java.lang.reflect.Method;
   import java.io.PrintStream;
   import java.util.ArrayList;
   import java.util.Enumeration;
   import java.util.HashMap;
  +import java.util.HashSet;
   import java.util.Stack;
   import java.security.AccessController;
   import java.security.PrivilegedActionException;
  @@ -551,6 +552,44 @@
       }
   
   
  +    /**
  +     * Gets the names of the methods supported by the underlying servlet.
  +     *
  +     * This is the same set of methods included in the Allow response header
  +     * in response to an OPTIONS request method processed by the underlying
  +     * servlet.
  +     *
  +     * @return Array of names of the methods supported by the underlying
  +     * servlet
  +     */
  +    public String[] getServletMethods() throws ServletException {
  +     
  +        HashSet allow = new HashSet();
  +        allow.add("TRACE");
  +        allow.add("OPTIONS");
  +     
  +        Method[] methods = getAllDeclaredMethods(loadServlet().getClass());
  +        for (int i=0; methods != null && i<methods.length; i++) {
  +            Method m = methods[i];
  +         
  +            if (m.getName().equals("doGet")) {
  +                allow.add("GET");
  +                allow.add("HEAD");
  +            } else if (m.getName().equals("doPost")) {
  +                allow.add("POST");
  +            } else if (m.getName().equals("doPut")) {
  +                allow.add("PUT");
  +            } else if (m.getName().equals("doDelete")) {
  +                allow.add("DELETE");
  +            }
  +        }
  +
  +        String[] methodNames = new String[allow.size()];
  +        return (String[]) allow.toArray(methodNames);
  +
  +    }
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
  @@ -1488,6 +1527,34 @@
           sb.append(']');
           return (sb.toString());
   
  +    }
  +
  +
  +    private Method[] getAllDeclaredMethods(Class c) {
  +
  +        if (c.equals(javax.servlet.http.HttpServlet.class)) {
  +            return null;
  +        }
  +
  +        Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
  +
  +        Method[] thisMethods = c.getDeclaredMethods();
  +        if (thisMethods == null) {
  +            return parentMethods;
  +        }
  +
  +        if ((parentMethods != null) && (parentMethods.length > 0)) {
  +            Method[] allMethods =
  +                new Method[parentMethods.length + thisMethods.length];
  +         System.arraycopy(parentMethods, 0, allMethods, 0,
  +                             parentMethods.length);
  +         System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
  +                             thisMethods.length);
  +
  +         thisMethods = allMethods;
  +     }
  +
  +     return thisMethods;
       }
   
   
  
  
  
  1.6       +14 -1     
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Wrapper.java
  
  Index: Wrapper.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Wrapper.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Wrapper.java      26 May 2004 15:28:42 -0000      1.5
  +++ Wrapper.java      27 Oct 2004 22:58:17 -0000      1.6
  @@ -132,6 +132,19 @@
   
   
       /**
  +     * Gets the names of the methods supported by the underlying servlet.
  +     *
  +     * This is the same set of methods included in the Allow response header
  +     * in response to an OPTIONS request method processed by the underlying
  +     * servlet.
  +     *
  +     * @return Array of names of the methods supported by the underlying
  +     * servlet
  +     */
  +    public String[] getServletMethods() throws ServletException;
  +
  +
  +    /**
        * Is this servlet currently unavailable?
        */
       public boolean isUnavailable();
  
  
  
  1.8       +32 -13    
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/CoyoteAdapter.java
  
  Index: CoyoteAdapter.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/CoyoteAdapter.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- CoyoteAdapter.java        19 Oct 2004 15:28:13 -0000      1.7
  +++ CoyoteAdapter.java        27 Oct 2004 22:58:17 -0000      1.8
  @@ -171,10 +171,11 @@
        * Parse additional request parameters.
        */
       protected boolean postParseRequest(org.apache.coyote.Request req, 
  -                                        Request request,
  -                                        org.apache.coyote.Response res, 
  -                                                                        Response 
response)
  -        throws Exception {
  +                                       Request request,
  +                                    org.apache.coyote.Response res, 
  +                                       Response response)
  +            throws Exception {
  +
           // XXX the processor needs to set a correct scheme and port prior to this 
point, 
           // in ajp13 protocols dont make sense to get the port from the connector..
           // XXX the processor may have set a correct scheme and port prior to this 
point, 
  @@ -190,14 +191,6 @@
               request.setSecure(connector.getSecure());
           }
   
  -        // Filter trace method
  -        if (!connector.getAllowTrace() 
  -            && req.method().equalsIgnoreCase("TRACE")) {
  -            res.setStatus(403);
  -            res.setMessage("TRACE method is not allowed");
  -            return false;
  -        }
  -
           // FIXME: the code below doesnt belongs to here, 
           // this is only have sense 
           // in Http11, not in ajp13..
  @@ -270,6 +263,32 @@
                                     request.getMappingData());
           request.setContext((Context) request.getMappingData().context);
           request.setWrapper((Wrapper) request.getMappingData().wrapper);
  +
  +        // Filter trace method
  +        if (!connector.getAllowTrace() 
  +                && req.method().equalsIgnoreCase("TRACE")) {
  +            Wrapper wrapper = request.getWrapper();
  +            String header = null;
  +            if (wrapper != null) {
  +                String[] methods = wrapper.getServletMethods();
  +                if (methods != null) {
  +                    for (int i=0; i<methods.length; i++) {
  +                        if ("TRACE".equals(methods[i])) {
  +                            continue;
  +                        }
  +                        if (header == null) {
  +                            header = methods[i];
  +                        } else {
  +                            header += ", " + methods[i];
  +                        }
  +                    }
  +                }
  +            }                               
  +            res.setStatus(405);
  +            res.addHeader("Allow", header);
  +            res.setMessage("TRACE method is not allowed");
  +            return false;
  +        }
   
           // Possible redirect
           MessageBytes redirectPathMB = request.getMappingData().redirectPath;
  
  
  

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

Reply via email to