You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by re...@apache.org on 2001/03/26 09:06:20 UTC

cvs commit: jakarta-slide/src/webdav/server/org/apache/slide/webdav/method AclMethod.java

remm        01/03/25 23:06:20

  Added:       src/webdav/server/org/apache/slide/webdav/method
                        AclMethod.java
  Log:
  - Support for WebDAV ACL ACL method.
  
  Revision  Changes    Path
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/AclMethod.java
  
  Index: AclMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/AclMethod.java,v 1.1 2001/03/26 07:06:20 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2001/03/26 07:06:20 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.w3c.dom.*;
  import org.xml.sax.InputSource;
  import org.xml.sax.SAXException;
  import org.apache.util.XMLPrinter;
  import org.apache.util.WebdavStatus;
  import org.apache.util.DOMWriter;
  import org.apache.slide.authenticate.CredentialsToken;
  import org.apache.slide.common.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.security.NodePermission;
  import org.apache.slide.webdav.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  import javax.xml.parsers.DocumentBuilder;
  
  /**
   * ACL method.
   *
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class AclMethod extends WebdavMethod {
      
      
      // -------------------------------------------------------------- Constants
      
      
      protected static final int PRIVILEGE_ALL = 0;
      protected static final int PRIVILEGE_READ = 1;
      protected static final int PRIVILEGE_READ_OBJECT = 2;
      protected static final int PRIVILEGE_READ_REVISION_METADATA = 3;
      protected static final int PRIVILEGE_READ_REVISION_CONTENT = 4;
      protected static final int PRIVILEGE_WRITE = 5;
      protected static final int PRIVILEGE_CREATE_OBJECT = 6;
      protected static final int PRIVILEGE_REMOVE_OBJECT = 7;
      protected static final int PRIVILEGE_LOCK_OBJECT = 8;
      protected static final int PRIVILEGE_READ_LOCKS = 9;
      protected static final int PRIVILEGE_CREATE_REVISION_METADATA = 10;
      protected static final int PRIVILEGE_MODIFY_REVISION_METADATA = 11;
      protected static final int PRIVILEGE_REMOVE_REVISION_METADATA = 12;
      protected static final int PRIVILEGE_CREATE_REVISION_CONTENT = 13;
      protected static final int PRIVILEGE_MODIFY_REVISION_CONTENT = 14;
      protected static final int PRIVILEGE_READ_ACL = 15;
      protected static final int PRIVILEGE_WRITE_ACL = 16;
      protected static final int PRIVILEGE_GRANT_PERMISSION = 17;
      protected static final int PRIVILEGE_REVOKE_PERMISSION = 18;
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Resource on which permissions will be modified.
       */
      protected String resourcePath;
      
      
      /**
       * Permissions to set.
       */
      protected Vector permissions = new Vector();
      
      
      /**
       * Namespace configuration.
       */
      protected NamespaceConfig config;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * ACL method constructor.
       *
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public AclMethod(GenericServlet servlet, NamespaceAccessToken token,
                       HttpServletRequest req, HttpServletResponse resp) {
          super(servlet, token, req, resp);
          readRequestContent();
          config = token.getNamespaceConfig();
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse the request.
       *
       * @exception WebdavException Bad request
       */
      protected void parseRequest()
          throws WebdavException {
          
          resourcePath = requestUri;
          if (resourcePath == null) {
              resourcePath = "/";
          }
          
          if (requestBody.length() != 0) {
              try {
                  
                  Document document = documentBuilder.parse(new InputSource(
                      (new StringReader(requestBody))));
                  
                  // Get the root element of the document
                  Element rootElement = document.getDocumentElement();
                  //NodeList childList = rootElement.getChildNodes();
                  
                  NodeList aclList = 
                      rootElement.getElementsByTagNameNS
                      (NodeProperty.DEFAULT_NAMESPACE, "acl");
                  
                  if (aclList.getLength() != 1) {
                      resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                      throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
                  }
                  
                  Element acl = (Element) aclList.item(0);
                  
                  NodeList aceList = acl.getElementsByTagNameNS
                      (NodeProperty.DEFAULT_NAMESPACE, "ace");
                  
                  for (int i = 0; i < aceList.getLength(); i++) {
                      
                      Element ace = (Element) aceList.item(i);
                      
                      // Ingnore inherited permissions
                      int inheritedCount = ace.getElementsByTagNameNS
                          (NodeProperty.DEFAULT_NAMESPACE, "inherited")
                          .getLength();
                      if (inheritedCount == 1)
                          continue;
                      if (inheritedCount > 1) {
                          resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                          throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
                      }
                      
                      // Ignore protected (protected <-> inherited for Slide)
                      int protectedCount = ace.getElementsByTagNameNS
                          (NodeProperty.DEFAULT_NAMESPACE, "protected")
                          .getLength();
                      if (protectedCount == 1)
                          continue;
                      if (protectedCount > 1) {
                          resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                          throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
                      }
                      
                      NodeList principalList = ace.getElementsByTagNameNS
                          (NodeProperty.DEFAULT_NAMESPACE, "principal");
                      if (principalList.getLength() != 1) {
                          resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                          throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
                      }
                      
                      Element principalElement = (Element) principalList.item(0);
                      String principal = parsePrincipal(principalElement);
                      
                      NodeList grantList = ace.getElementsByTagNameNS
                          (NodeProperty.DEFAULT_NAMESPACE, "grant");
                      NodeList denyList = ace.getElementsByTagNameNS
                          (NodeProperty.DEFAULT_NAMESPACE, "deny");
                      
                      if ((grantList.getLength() > 0) && 
                          (denyList.getLength() > 0)) {
                          resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                          throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
                      }
                      if ((grantList.getLength() == 0) && 
                          (denyList.getLength() == 0)) {
                          resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                          throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
                      }
                      
                      boolean negative = (denyList.getLength() > 0);
                      
                      NodeList privilegeList = null;
                      
                      if (negative) {
                          privilegeList = denyList;
                      } else {
                          privilegeList = grantList;
                      }
                      
                      boolean inheritable = true; 
                      // FIXME : Use the very unofficial Advanced ACL spec here.
                      
                      for (int j = 0; i < privilegeList.getLength(); j++) {
                          
                          Element privilegeElement = 
                              (Element) privilegeList.item(j);
                          int privilege = parsePrivilege(privilegeElement);
                          
                          switch (privilege) {
                          case PRIVILEGE_ALL:
                              addPermission(principal, "/", 
                                            negative, inheritable);
                              break;
                          case PRIVILEGE_READ:
                              addPermission
                                  (principal, 
                                   config.getReadObjectAction().getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getReadRevisionMetadataAction()
                                   .getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getReadRevisionContentAction()
                                   .getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getReadLocksAction().getUri(), 
                                   negative, inheritable);
                              break;
                          case PRIVILEGE_READ_OBJECT:
                              addPermission
                                  (principal, 
                                   config.getReadObjectAction().getUri(), 
                                   negative, inheritable);
                              break;
                          case PRIVILEGE_READ_REVISION_METADATA:
                              addPermission
                                  (principal, 
                                   config.getReadRevisionMetadataAction()
                                   .getUri(), 
                                   negative, inheritable);
                              break;
                          case PRIVILEGE_READ_REVISION_CONTENT:
                              addPermission
                                  (principal, 
                                   config.getReadRevisionContentAction()
                                   .getUri(), 
                                   negative, inheritable);
                              break;
                          case PRIVILEGE_WRITE:
                              addPermission
                                  (principal, 
                                   config.getCreateObjectAction().getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getRemoveObjectAction().getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getLockObjectAction().getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getCreateRevisionMetadataAction()
                                   .getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getModifyRevisionMetadataAction()
                                   .getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getRemoveRevisionMetadataAction()
                                   .getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getCreateRevisionContentAction()
                                   .getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getModifyRevisionContentAction()
                                   .getUri(), 
                                   negative, inheritable);
                              break;
                          case PRIVILEGE_READ_ACL:
                              addPermission
                                  (principal, 
                                   config.getReadPermissionsAction().getUri(), 
                                   negative, inheritable);
                              break;
                          case PRIVILEGE_WRITE_ACL:
                              addPermission
                                  (principal, 
                                   config.getGrantPermissionAction().getUri(), 
                                   negative, inheritable);
                              addPermission
                                  (principal, 
                                   config.getRevokePermissionAction().getUri(), 
                                   negative, inheritable);
                              break;
                          case PRIVILEGE_GRANT_PERMISSION:
                              addPermission
                                  (principal, 
                                   config.getGrantPermissionAction().getUri(), 
                                   negative, inheritable);
                              break;
                          case PRIVILEGE_REVOKE_PERMISSION:
                              addPermission
                                  (principal, 
                                   config.getRevokePermissionAction().getUri(), 
                                   negative, inheritable);
                              break;
                          }
                          
                      }
                      
                  }
                  
              } catch (SAXException e) {
                  resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                  throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
              } catch (IOException e) {
                  e.printStackTrace();
                  resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                  throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
              }
          } else {
              try {
                  resp.sendError(WebdavStatus.SC_BAD_REQUEST,
                                  WebdavStatus.getStatusText
                                 (WebdavStatus.SC_BAD_REQUEST));
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          
      }
      
      
      /**
       * Execute the request.
       *
       * @exception WebdavException
       */
      protected void executeRequest()
          throws WebdavException {
          
          try {
              
              security.setPermissions(slideToken, resourcePath, 
                                      permissions.elements());
              
          } catch (ObjectNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
          } catch (AccessDeniedException e) {
              // 403 - Forbidden
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_FORBIDDEN);
          } catch (ServiceAccessException e) {
              // 500 - Internal server error
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
          } catch (RuntimeException e) {
              // 500 - Internal server error
              e.printStackTrace();
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
          }
          
      }
      
      
      /**
       * Returns true
       */
      protected boolean methodNeedsTransactionSupport() {
          return true;
      }
      
      
      /**
       * Parse principal.
       * 
       * @return the URI of the principal
       */
      protected String parsePrincipal(Element principal)
          throws WebdavException {
          NodeList hrefList = 
              principal.getElementsByTagNameNS(NodeProperty.DEFAULT_NAMESPACE, 
                                               "href");
          if (hrefList.getLength() == 1) {
              Element href = (Element) hrefList.item(0);
              if (href.getFirstChild().getNodeType() == Node.TEXT_NODE)
                  return href.getFirstChild().getNodeValue();
          } else if (hasChild(principal, NodeProperty.DEFAULT_NAMESPACE, 
                              "all")) {
              return "/";
          } else if (hasChild(principal, NodeProperty.DEFAULT_NAMESPACE, 
                              "unauthenticated")) {
              return token.getNamespaceConfig().getUsersPath() + "/"
                  + token.getNamespaceConfig().getGuestPath();
          }
          throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
      }
      
      
      /**
       * Parse privilege.
       * 
       * @return privilege
       */
      protected int parsePrivilege(Element privilege)
          throws WebdavException {
          
          if (hasChild(privilege, NodeProperty.DEFAULT_NAMESPACE, "all")) {
              return PRIVILEGE_ALL;
          } else if (hasChild(privilege, NodeProperty.DEFAULT_NAMESPACE, 
                              "read")) {
              return PRIVILEGE_READ;
          } else if (hasChild(privilege, NodeProperty.DEFAULT_NAMESPACE, 
                              "write")) {
              return PRIVILEGE_WRITE;
          } else if (hasChild(privilege, NodeProperty.DEFAULT_NAMESPACE, 
                              "read-acl")) {
              return PRIVILEGE_READ_ACL;
          } else if (hasChild(privilege, NodeProperty.DEFAULT_NAMESPACE, 
                              "write-acl")) {
              return PRIVILEGE_WRITE_ACL;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, "read-object")) {
              return PRIVILEGE_READ_OBJECT;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "read-revision-metadata")) {
              return PRIVILEGE_READ_REVISION_METADATA;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "read-revision-content")) {
              return PRIVILEGE_READ_REVISION_CONTENT;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, "create-object")) {
              return PRIVILEGE_CREATE_OBJECT;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, "remove-object")) {
              return PRIVILEGE_REMOVE_OBJECT;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, "lock-object")) {
              return PRIVILEGE_LOCK_OBJECT;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, "read-locks")) {
              return PRIVILEGE_READ_LOCKS;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "create-revision-metadata")) {
              return PRIVILEGE_CREATE_REVISION_METADATA;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "modify-revision-metadata")) {
              return PRIVILEGE_MODIFY_REVISION_METADATA;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "remove-revision-metadata")) {
              return PRIVILEGE_REMOVE_REVISION_METADATA;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "create-revision-content")) {
              return PRIVILEGE_CREATE_REVISION_CONTENT;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "modify-revision-content")) {
              return PRIVILEGE_MODIFY_REVISION_CONTENT;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "grant-permission")) {
              return PRIVILEGE_GRANT_PERMISSION;
          } else if (hasChild(privilege, SLIDE_NAMESPACE, 
                              "revoke-permission")) {
              return PRIVILEGE_REVOKE_PERMISSION;
          } else {
              throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
          }
          
      }
      
      
      /**
       * Has specified child element ?
       */
      protected boolean hasChild(Element element, String namespace, 
                                 String name) {
          return 
              (element.getElementsByTagNameNS(namespace, name).getLength() == 1);
      }
      
      
          
      /**
       * Add permission to the list of permissions to set.
       */
      protected void addPermission(String principal, String action, 
                                   boolean negative, boolean inheritable) {
          NodePermission permission = new NodePermission
              (resourcePath, principal, action, inheritable, negative);
          if (!permissions.contains(permission))
              permissions.addElement(permission);
      }
      
      
  }