tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amy...@apache.org
Subject cvs commit: jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm Constants.java JAASMemoryLoginModule.java RealmBase.java
Date Fri, 09 Aug 2002 01:12:40 GMT
amyroh      2002/08/08 18:12:39

  Modified:    catalina/src/share/org/apache/catalina Realm.java
               catalina/src/share/org/apache/catalina/authenticator
                        AuthenticatorBase.java
               catalina/src/share/org/apache/catalina/realm Constants.java
                        JAASMemoryLoginModule.java RealmBase.java
  Log:
  Complete the move of the authorization logic from the
  o.a.c.authenticator.AuthenticatorBase to the o.a.c.realm.RealmBase.
  
  Patch submitted by Jean-francois Arcand.
  
  Revision  Changes    Path
  1.3       +33 -11    jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Realm.java
  
  Index: Realm.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Realm.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Realm.java	7 Aug 2002 20:51:44 -0000	1.2
  +++ Realm.java	9 Aug 2002 01:12:39 -0000	1.3
  @@ -64,7 +64,6 @@
   
   package org.apache.catalina;
   
  -
   import java.beans.PropertyChangeListener;
   import java.io.IOException;
   import java.security.Principal;
  @@ -171,7 +170,14 @@
        */
       public Principal authenticate(X509Certificate certs[]);
       
  -
  +    /**
  +     * Return the SecurityConstraint configured to guard the request URI for
  +     * this request, or <code>null</code> if there is no such constraint.
  +     *
  +     * @param request Request we are processing
  +     */
  +    public SecurityConstraint findSecurityConstraint(HttpRequest request,
  +                                                     Context context);
       /**
        * Perform access control based on the specified authorization constraint.
        * Return <code>true</code> if this constraint is satisfied and processing
  @@ -184,10 +190,10 @@
        *
        * @exception IOException if an input/output error occurs
        */
  -    public boolean hasResourceAccess(HttpRequest request,
  -                                     HttpResponse response,
  -                                     SecurityConstraint constraint,
  -                                     Context context)
  +    public boolean hasResourcePermission(HttpRequest request,
  +                                         HttpResponse response,
  +                                         SecurityConstraint constraint,
  +                                         Context context)
           throws IOException;
       
       
  @@ -201,7 +207,23 @@
        */
       public boolean hasRole(Principal principal, String role);
   
  -
  +        /**
  +     * Enforce any user data constraint required by the security constraint
  +     * guarding this request URI.  Return <code>true</code> if this constraint
  +     * was not violated and processing should continue, or <code>false</code>
  +     * if we have created a response already.
  +     *
  +     * @param request Request we are processing
  +     * @param response Response we are creating
  +     * @param constraint Security constraint being checked
  +     *
  +     * @exception IOException if an input/output error occurs
  +     */
  +    public boolean hasUserDataPermission(HttpRequest request,
  +                                         HttpResponse response,
  +                                         SecurityConstraint constraint)
  +        throws IOException;
  +    
       /**
        * Remove a property change listener from this component.
        *
  
  
  
  1.3       +14 -143   jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java
  
  Index: AuthenticatorBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- AuthenticatorBase.java	7 Aug 2002 20:51:44 -0000	1.2
  +++ AuthenticatorBase.java	9 Aug 2002 01:12:39 -0000	1.3
  @@ -462,8 +462,11 @@
               }
           }
   
  +        Realm realm = this.context.getRealm();
           // Is this request URI subject to a security constraint?
  -        SecurityConstraint constraint = findConstraint(hrequest);
  +        SecurityConstraint constraint = realm.
  +                                findSecurityConstraint(hrequest, this.context);
  +       
           if ((constraint == null) /* &&
               (!Constants.FORM_METHOD.equals(config.getAuthMethod())) */ ) {
               if (debug >= 1)
  @@ -486,10 +489,11 @@
   
           // Enforce any user data constraint for this security constraint
           if (debug >= 1)
  -            log(" Calling checkUserData()");
  -        if (!checkUserData(hrequest, hresponse, constraint)) {
  +            log(" Calling hasUserDataPermission()");
  +        
  +        if (!realm.hasUserDataPermission(hrequest, hresponse, constraint)) {
               if (debug >= 1)
  -                log(" Failed checkUserData() test");
  +                log(" Failed hasUserDataPermission() test");
               // ASSERT: Authenticator already set the appropriate
               // HTTP status code, so we do not have to do anything special
               return;
  @@ -512,7 +516,8 @@
           if (constraint.getAuthConstraint()) {
               if (debug >= 1)
                   log(" Calling accessControl()");
  -            if (!this.context.getRealm().hasResourceAccess(hrequest, hresponse, constraint,
this.context)) {
  +            
  +            if (!realm.hasResourcePermission(hrequest, hresponse, constraint, this.context))
{
                   if (debug >= 1)
                       log(" Failed accessControl() test");
                   // ASSERT: AccessControl method has already set the appropriate
  @@ -567,140 +572,6 @@
                                               HttpResponse response,
                                               LoginConfig config)
           throws IOException;
  -
  -
  -    /**
  -     * Enforce any user data constraint required by the security constraint
  -     * guarding this request URI.  Return <code>true</code> if this constraint
  -     * was not violated and processing should continue, or <code>false</code>
  -     * if we have created a response already.
  -     *
  -     * @param request Request we are processing
  -     * @param response Response we are creating
  -     * @param constraint Security constraint being checked
  -     *
  -     * @exception IOException if an input/output error occurs
  -     */
  -    protected boolean checkUserData(HttpRequest request,
  -                                    HttpResponse response,
  -                                    SecurityConstraint constraint)
  -        throws IOException {
  -
  -        // Is there a relevant user data constraint?
  -        if (constraint == null) {
  -            if (debug >= 2)
  -                log("  No applicable security constraint defined");
  -            return (true);
  -        }
  -        String userConstraint = constraint.getUserConstraint();
  -        if (userConstraint == null) {
  -            if (debug >= 2)
  -                log("  No applicable user data constraint defined");
  -            return (true);
  -        }
  -        if (userConstraint.equals(Constants.NONE_TRANSPORT)) {
  -            if (debug >= 2)
  -                log("  User data constraint has no restrictions");
  -            return (true);
  -        }
  -
  -        // Validate the request against the user data constraint
  -        if (request.getRequest().isSecure()) {
  -            if (debug >= 2)
  -                log("  User data constraint already satisfied");
  -            return (true);
  -        }
  -
  -        // Initialize variables we need to determine the appropriate action
  -        HttpServletRequest hrequest =
  -            (HttpServletRequest) request.getRequest();
  -        HttpServletResponse hresponse =
  -            (HttpServletResponse) response.getResponse();
  -        int redirectPort = request.getConnector().getRedirectPort();
  -
  -        // Is redirecting disabled?
  -        if (redirectPort <= 0) {
  -            if (debug >= 2)
  -                log("  SSL redirect is disabled");
  -            hresponse.sendError
  -                (HttpServletResponse.SC_FORBIDDEN,
  -                 hrequest.getRequestURI());
  -            return (false);
  -        }
  -
  -        // Redirect to the corresponding SSL port
  -        String protocol = "https";
  -        String host = hrequest.getServerName();
  -        StringBuffer file = new StringBuffer(hrequest.getRequestURI());
  -        String requestedSessionId = hrequest.getRequestedSessionId();
  -        if ((requestedSessionId != null) &&
  -            hrequest.isRequestedSessionIdFromURL()) {
  -            file.append(";jsessionid=");
  -            file.append(requestedSessionId);
  -        }
  -        String queryString = hrequest.getQueryString();
  -        if (queryString != null) {
  -            file.append('?');
  -            file.append(queryString);
  -        }
  -        URL url = null;
  -        try {
  -            url = new URL(protocol, host, redirectPort, file.toString());
  -            if (debug >= 2)
  -                log("  Redirecting to " + url.toString());
  -            hresponse.sendRedirect(url.toString());
  -            return (false);
  -        } catch (MalformedURLException e) {
  -            if (debug >= 2)
  -                log("  Cannot create new URL", e);
  -            hresponse.sendError
  -                (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  -                 hrequest.getRequestURI());
  -            return (false);
  -        }
  -
  -    }
  -
  -
  -    /**
  -     * Return the SecurityConstraint configured to guard the request URI for
  -     * this request, or <code>null</code> if there is no such constraint.
  -     *
  -     * @param request Request we are processing
  -     */
  -    protected SecurityConstraint findConstraint(HttpRequest request) {
  -
  -        // Are there any defined security constraints?
  -        SecurityConstraint constraints[] = context.findConstraints();
  -        if ((constraints == null) || (constraints.length == 0)) {
  -            if (debug >= 2)
  -                log("  No applicable constraints defined");
  -            return (null);
  -        }
  -
  -        // Check each defined security constraint
  -        HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
  -        String uri = request.getDecodedRequestURI();
  -        String contextPath = hreq.getContextPath();
  -        if (contextPath.length() > 0)
  -            uri = uri.substring(contextPath.length());
  -        uri = RequestUtil.URLDecode(uri); // Before checking constraints
  -        String method = hreq.getMethod();
  -        for (int i = 0; i < constraints.length; i++) {
  -            if (debug >= 2)
  -                log("  Checking constraint '" + constraints[i] +
  -                    "' against " + method + " " + uri + " --> " +
  -                    constraints[i].included(uri, method));
  -            if (constraints[i].included(uri, method))
  -                return (constraints[i]);
  -        }
  -
  -        // No applicable security constraint was found
  -        if (debug >= 2)
  -            log("  No applicable constraint located");
  -        return (null);
  -
  -    }
   
   
       /**
  
  
  
  1.3       +8 -4      jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/Constants.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Constants.java	7 Aug 2002 20:51:44 -0000	1.2
  +++ Constants.java	9 Aug 2002 01:12:39 -0000	1.3
  @@ -83,5 +83,9 @@
       // Form based authentication constants
       public static final String FORM_ACTION = "/j_security_check";
   
  +    // User data constraints for transport guarantee
  +    public static final String NONE_TRANSPORT = "NONE";
  +    public static final String INTEGRAL_TRANSPORT = "INTEGRAL";
  +    public static final String CONFIDENTIAL_TRANSPORT = "CONFIDENTIAL";
   
   }
  
  
  
  1.3       +144 -8    jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/JAASMemoryLoginModule.java
  
  Index: JAASMemoryLoginModule.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/JAASMemoryLoginModule.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JAASMemoryLoginModule.java	7 Aug 2002 20:51:44 -0000	1.2
  +++ JAASMemoryLoginModule.java	9 Aug 2002 01:12:39 -0000	1.3
  @@ -67,6 +67,8 @@
   import java.beans.PropertyChangeListener;
   import java.io.File;
   import java.io.IOException;
  +import java.net.URL;
  +import java.net.MalformedURLException;
   import java.util.ArrayList;
   import java.util.HashMap;
   import java.util.Map;
  @@ -94,6 +96,7 @@
   import org.apache.catalina.deploy.LoginConfig;
   import org.apache.catalina.deploy.SecurityConstraint;
   import org.apache.catalina.util.StringManager;
  +import org.apache.catalina.util.RequestUtil;
   import org.apache.commons.digester.Digester;
   
   
  @@ -279,7 +282,49 @@
   
       }
   
  +    
  +    /**
  +     * Return the SecurityConstraint configured to guard the request URI for
  +     * this request, or <code>null</code> if there is no such constraint.
  +     *
  +     * @param request Request we are processing
  +     */
  +    public SecurityConstraint findSecurityConstraint(HttpRequest request,
  +                                                     Context context) {
  +
  +        // Are there any defined security constraints?
  +        SecurityConstraint constraints[] = context.findConstraints();
  +        if ((constraints == null) || (constraints.length == 0)) {
  +            if (debug)
  +                log("  No applicable constraints defined");
  +            return (null);
  +        }
  +
  +        // Check each defined security constraint
  +        HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
  +        String uri = request.getDecodedRequestURI();
  +        String contextPath = hreq.getContextPath();
  +        if (contextPath.length() > 0)
  +            uri = uri.substring(contextPath.length());
  +        uri = RequestUtil.URLDecode(uri); // Before checking constraints
  +        String method = hreq.getMethod();
  +        for (int i = 0; i < constraints.length; i++) {
  +            if (debug)
  +                log("  Checking constraint '" + constraints[i] +
  +                    "' against " + method + " " + uri + " --> " +
  +                    constraints[i].included(uri, method));
  +            if (constraints[i].included(uri, method))
  +                return (constraints[i]);
  +        }
   
  +        // No applicable security constraint was found
  +        if (debug)
  +            log("  No applicable constraint located");
  +        return (null);
  +
  +    }
  +    
  +    
       /**
        * Initialize this <code>LoginModule</code> with the specified
        * configuration information.
  @@ -590,10 +635,10 @@
        *
        * @exception IOException if an input/output error occurs
        */
  -    public boolean hasResourceAccess(HttpRequest request,
  -                                     HttpResponse response,
  -                                     SecurityConstraint constraint,
  -                                     Context context)
  +    public boolean hasResourcePermission(HttpRequest request,
  +                                         HttpResponse response,
  +                                         SecurityConstraint constraint,
  +                                         Context context)
           throws IOException {
   
           if (constraint == null)
  @@ -661,6 +706,97 @@
   
       } 
       
  +    /**
  +     * Enforce any user data constraint required by the security constraint
  +     * guarding this request URI.  Return <code>true</code> if this constraint
  +     * was not violated and processing should continue, or <code>false</code>
  +     * if we have created a response already.
  +     *
  +     * @param request Request we are processing
  +     * @param response Response we are creating
  +     * @param constraint Security constraint being checked
  +     *
  +     * @exception IOException if an input/output error occurs
  +     */
  +    public boolean hasUserDataPermission(HttpRequest request,
  +                                         HttpResponse response,
  +                                         SecurityConstraint constraint)
  +        throws IOException {
  +
  +        // Is there a relevant user data constraint?
  +        if (constraint == null) {
  +            if (debug)
  +                log("  No applicable security constraint defined");
  +            return (true);
  +        }
  +        String userConstraint = constraint.getUserConstraint();
  +        if (userConstraint == null) {
  +            if (debug)
  +                log("  No applicable user data constraint defined");
  +            return (true);
  +        }
  +        if (userConstraint.equals(Constants.NONE_TRANSPORT)) {
  +            if (debug)
  +                log("  User data constraint has no restrictions");
  +            return (true);
  +        }
  +
  +        // Validate the request against the user data constraint
  +        if (request.getRequest().isSecure()) {
  +            if (debug)
  +                log("  User data constraint already satisfied");
  +            return (true);
  +        }
  +
  +        // Initialize variables we need to determine the appropriate action
  +        HttpServletRequest hrequest =
  +            (HttpServletRequest) request.getRequest();
  +        HttpServletResponse hresponse =
  +            (HttpServletResponse) response.getResponse();
  +        int redirectPort = request.getConnector().getRedirectPort();
  +
  +        // Is redirecting disabled?
  +        if (redirectPort <= 0) {
  +            if (debug)
  +                log("  SSL redirect is disabled");
  +            hresponse.sendError
  +                (HttpServletResponse.SC_FORBIDDEN,
  +                 hrequest.getRequestURI());
  +            return (false);
  +        }
  +
  +        // Redirect to the corresponding SSL port
  +        String protocol = "https";
  +        String host = hrequest.getServerName();
  +        StringBuffer file = new StringBuffer(hrequest.getRequestURI());
  +        String requestedSessionId = hrequest.getRequestedSessionId();
  +        if ((requestedSessionId != null) &&
  +            hrequest.isRequestedSessionIdFromURL()) {
  +            file.append(";jsessionid=");
  +            file.append(requestedSessionId);
  +        }
  +        String queryString = hrequest.getQueryString();
  +        if (queryString != null) {
  +            file.append('?');
  +            file.append(queryString);
  +        }
  +        URL url = null;
  +        try {
  +            url = new URL(protocol, host, redirectPort, file.toString());
  +            if (debug)
  +                log("  Redirecting to " + url.toString());
  +            hresponse.sendRedirect(url.toString());
  +            return (false);
  +        } catch (MalformedURLException e) {
  +            if (debug)
  +                log("  Cannot create new URL", e);
  +            hresponse.sendError
  +                (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  +                 hrequest.getRequestURI());
  +            return (false);
  +        }
  +
  +    }
   
   
   }
  
  
  
  1.3       +146 -8    jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/RealmBase.java
  
  Index: RealmBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/RealmBase.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RealmBase.java	7 Aug 2002 20:51:44 -0000	1.2
  +++ RealmBase.java	9 Aug 2002 01:12:39 -0000	1.3
  @@ -73,6 +73,8 @@
   import java.security.cert.X509Certificate;
   import java.io.File;
   import java.io.IOException;
  +import java.net.URL;
  +import java.net.MalformedURLException;
   
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
  @@ -93,6 +95,7 @@
   import org.apache.catalina.util.LifecycleSupport;
   import org.apache.catalina.util.StringManager;
   import org.apache.catalina.util.MD5Encoder;
  +import org.apache.catalina.util.RequestUtil;
   
   
   /**
  @@ -429,6 +432,47 @@
   
       }
   
  +    /**
  +     * Return the SecurityConstraint configured to guard the request URI for
  +     * this request, or <code>null</code> if there is no such constraint.
  +     *
  +     * @param request Request we are processing
  +     */
  +    public SecurityConstraint findSecurityConstraint(HttpRequest request,
  +                                                     Context context) {
  +
  +        // Are there any defined security constraints?
  +        SecurityConstraint constraints[] = context.findConstraints();
  +        if ((constraints == null) || (constraints.length == 0)) {
  +            if (debug >= 2)
  +                log("  No applicable constraints defined");
  +            return (null);
  +        }
  +
  +        // Check each defined security constraint
  +        HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
  +        String uri = request.getDecodedRequestURI();
  +        String contextPath = hreq.getContextPath();
  +        if (contextPath.length() > 0)
  +            uri = uri.substring(contextPath.length());
  +        uri = RequestUtil.URLDecode(uri); // Before checking constraints
  +        String method = hreq.getMethod();
  +        for (int i = 0; i < constraints.length; i++) {
  +            if (debug >= 2)
  +                log("  Checking constraint '" + constraints[i] +
  +                    "' against " + method + " " + uri + " --> " +
  +                    constraints[i].included(uri, method));
  +            if (constraints[i].included(uri, method))
  +                return (constraints[i]);
  +        }
  +
  +        // No applicable security constraint was found
  +        if (debug >= 2)
  +            log("  No applicable constraint located");
  +        return (null);
  +
  +    }
  + 
       
       /**
        * Perform access control based on the specified authorization constraint.
  @@ -442,10 +486,10 @@
        *
        * @exception IOException if an input/output error occurs
        */
  -    public boolean hasResourceAccess(HttpRequest request,
  -                                     HttpResponse response,
  -                                     SecurityConstraint constraint,
  -                                     Context context)
  +    public boolean hasResourcePermission(HttpRequest request,
  +                                         HttpResponse response,
  +                                         SecurityConstraint constraint,
  +                                         Context context)
           throws IOException {
   
           if (constraint == null)
  @@ -545,7 +589,100 @@
   
       }
   
  +    
  +    /**
  +     * Enforce any user data constraint required by the security constraint
  +     * guarding this request URI.  Return <code>true</code> if this constraint
  +     * was not violated and processing should continue, or <code>false</code>
  +     * if we have created a response already.
  +     *
  +     * @param request Request we are processing
  +     * @param response Response we are creating
  +     * @param constraint Security constraint being checked
  +     *
  +     * @exception IOException if an input/output error occurs
  +     */
  +    public boolean hasUserDataPermission(HttpRequest request,
  +                                    HttpResponse response,
  +                                    SecurityConstraint constraint)
  +        throws IOException {
  +
  +        // Is there a relevant user data constraint?
  +        if (constraint == null) {
  +            if (debug >= 2)
  +                log("  No applicable security constraint defined");
  +            return (true);
  +        }
  +        String userConstraint = constraint.getUserConstraint();
  +        if (userConstraint == null) {
  +            if (debug >= 2)
  +                log("  No applicable user data constraint defined");
  +            return (true);
  +        }
  +        if (userConstraint.equals(Constants.NONE_TRANSPORT)) {
  +            if (debug >= 2)
  +                log("  User data constraint has no restrictions");
  +            return (true);
  +        }
  +
  +        // Validate the request against the user data constraint
  +        if (request.getRequest().isSecure()) {
  +            if (debug >= 2)
  +                log("  User data constraint already satisfied");
  +            return (true);
  +        }
  +
  +        // Initialize variables we need to determine the appropriate action
  +        HttpServletRequest hrequest =
  +            (HttpServletRequest) request.getRequest();
  +        HttpServletResponse hresponse =
  +            (HttpServletResponse) response.getResponse();
  +        int redirectPort = request.getConnector().getRedirectPort();
  +
  +        // Is redirecting disabled?
  +        if (redirectPort <= 0) {
  +            if (debug >= 2)
  +                log("  SSL redirect is disabled");
  +            hresponse.sendError
  +                (HttpServletResponse.SC_FORBIDDEN,
  +                 hrequest.getRequestURI());
  +            return (false);
  +        }
  +
  +        // Redirect to the corresponding SSL port
  +        String protocol = "https";
  +        String host = hrequest.getServerName();
  +        StringBuffer file = new StringBuffer(hrequest.getRequestURI());
  +        String requestedSessionId = hrequest.getRequestedSessionId();
  +        if ((requestedSessionId != null) &&
  +            hrequest.isRequestedSessionIdFromURL()) {
  +            file.append(";jsessionid=");
  +            file.append(requestedSessionId);
  +        }
  +        String queryString = hrequest.getQueryString();
  +        if (queryString != null) {
  +            file.append('?');
  +            file.append(queryString);
  +        }
  +        URL url = null;
  +        try {
  +            url = new URL(protocol, host, redirectPort, file.toString());
  +            if (debug >= 2)
  +                log("  Redirecting to " + url.toString());
  +            hresponse.sendRedirect(url.toString());
  +            return (false);
  +        } catch (MalformedURLException e) {
  +            if (debug >= 2)
  +                log("  Cannot create new URL", e);
  +            hresponse.sendError
  +                (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  +                 hrequest.getRequestURI());
  +            return (false);
  +        }
   
  +    }
  +    
  +    
       /**
        * Remove a property change listener from this component.
        *
  @@ -825,5 +962,6 @@
           }
   
       }
  +    
   
   }
  
  
  

--
To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>


Mime
View raw message