Search in sources :

Example 1 with DOMWriter

use of org.apache.catalina.util.DOMWriter in project tomcat70 by apache.

the class WebdavStatus method doLock.

/**
 * LOCK Method.
 */
protected void doLock(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    if (readOnly) {
        resp.sendError(WebdavStatus.SC_FORBIDDEN);
        return;
    }
    if (isLocked(req)) {
        resp.sendError(WebdavStatus.SC_LOCKED);
        return;
    }
    LockInfo lock = new LockInfo();
    // Parsing lock request
    // Parsing depth header
    String depthStr = req.getHeader("Depth");
    if (depthStr == null) {
        lock.depth = maxDepth;
    } else {
        if (depthStr.equals("0")) {
            lock.depth = 0;
        } else {
            lock.depth = maxDepth;
        }
    }
    // Parsing timeout header
    int lockDuration = DEFAULT_TIMEOUT;
    String lockDurationStr = req.getHeader("Timeout");
    if (lockDurationStr == null) {
        lockDuration = DEFAULT_TIMEOUT;
    } else {
        int commaPos = lockDurationStr.indexOf(',');
        // If multiple timeouts, just use the first
        if (commaPos != -1) {
            lockDurationStr = lockDurationStr.substring(0, commaPos);
        }
        if (lockDurationStr.startsWith("Second-")) {
            lockDuration = Integer.parseInt(lockDurationStr.substring(7));
        } else {
            if (lockDurationStr.equalsIgnoreCase("infinity")) {
                lockDuration = MAX_TIMEOUT;
            } else {
                try {
                    lockDuration = Integer.parseInt(lockDurationStr);
                } catch (NumberFormatException e) {
                    lockDuration = MAX_TIMEOUT;
                }
            }
        }
        if (lockDuration == 0) {
            lockDuration = DEFAULT_TIMEOUT;
        }
        if (lockDuration > MAX_TIMEOUT) {
            lockDuration = MAX_TIMEOUT;
        }
    }
    lock.expiresAt = System.currentTimeMillis() + (lockDuration * 1000);
    int lockRequestType = LOCK_CREATION;
    Node lockInfoNode = null;
    DocumentBuilder documentBuilder = getDocumentBuilder();
    try {
        Document document = documentBuilder.parse(new InputSource(req.getInputStream()));
        // Get the root element of the document
        Element rootElement = document.getDocumentElement();
        lockInfoNode = rootElement;
    } catch (IOException e) {
        lockRequestType = LOCK_REFRESH;
    } catch (SAXException e) {
        lockRequestType = LOCK_REFRESH;
    }
    if (lockInfoNode != null) {
        // Reading lock information
        NodeList childList = lockInfoNode.getChildNodes();
        StringWriter strWriter = null;
        DOMWriter domWriter = null;
        Node lockScopeNode = null;
        Node lockTypeNode = null;
        Node lockOwnerNode = null;
        for (int i = 0; i < childList.getLength(); i++) {
            Node currentNode = childList.item(i);
            switch(currentNode.getNodeType()) {
                case Node.TEXT_NODE:
                    break;
                case Node.ELEMENT_NODE:
                    String nodeName = currentNode.getNodeName();
                    if (nodeName.endsWith("lockscope")) {
                        lockScopeNode = currentNode;
                    }
                    if (nodeName.endsWith("locktype")) {
                        lockTypeNode = currentNode;
                    }
                    if (nodeName.endsWith("owner")) {
                        lockOwnerNode = currentNode;
                    }
                    break;
            }
        }
        if (lockScopeNode != null) {
            childList = lockScopeNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        break;
                    case Node.ELEMENT_NODE:
                        String tempScope = currentNode.getNodeName();
                        if (tempScope.indexOf(':') != -1) {
                            lock.scope = tempScope.substring(tempScope.indexOf(':') + 1);
                        } else {
                            lock.scope = tempScope;
                        }
                        break;
                }
            }
            if (lock.scope == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            // Bad request
            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
        }
        if (lockTypeNode != null) {
            childList = lockTypeNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        break;
                    case Node.ELEMENT_NODE:
                        String tempType = currentNode.getNodeName();
                        if (tempType.indexOf(':') != -1) {
                            lock.type = tempType.substring(tempType.indexOf(':') + 1);
                        } else {
                            lock.type = tempType;
                        }
                        break;
                }
            }
            if (lock.type == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            // Bad request
            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
        }
        if (lockOwnerNode != null) {
            childList = lockOwnerNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        lock.owner += currentNode.getNodeValue();
                        break;
                    case Node.ELEMENT_NODE:
                        strWriter = new StringWriter();
                        domWriter = new DOMWriter(strWriter, true);
                        domWriter.setQualifiedNames(false);
                        domWriter.print(currentNode);
                        lock.owner += strWriter.toString();
                        break;
                }
            }
            if (lock.owner == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            lock.owner = "";
        }
    }
    String path = getRelativePath(req);
    lock.path = path;
    boolean exists = true;
    Object object = null;
    try {
        object = resources.lookup(path);
    } catch (NamingException e) {
        exists = false;
    }
    Enumeration<LockInfo> locksList = null;
    if (lockRequestType == LOCK_CREATION) {
        // Generating lock id
        String lockTokenStr = req.getServletPath() + "-" + lock.type + "-" + lock.scope + "-" + req.getUserPrincipal() + "-" + lock.depth + "-" + lock.owner + "-" + lock.tokens + "-" + lock.expiresAt + "-" + System.currentTimeMillis() + "-" + secret;
        String lockToken = MD5Encoder.encode(md5Helper.digest(lockTokenStr.getBytes(Charset.defaultCharset())));
        if ((exists) && (object instanceof DirContext) && (lock.depth == maxDepth)) {
            // Locking a collection (and all its member resources)
            // Checking if a child resource of this collection is
            // already locked
            Vector<String> lockPaths = new Vector<String>();
            locksList = collectionLocks.elements();
            while (locksList.hasMoreElements()) {
                LockInfo currentLock = locksList.nextElement();
                if (currentLock.hasExpired()) {
                    resourceLocks.remove(currentLock.path);
                    continue;
                }
                if ((currentLock.path.startsWith(lock.path)) && ((currentLock.isExclusive()) || (lock.isExclusive()))) {
                    // A child collection of this collection is locked
                    lockPaths.addElement(currentLock.path);
                }
            }
            locksList = resourceLocks.elements();
            while (locksList.hasMoreElements()) {
                LockInfo currentLock = locksList.nextElement();
                if (currentLock.hasExpired()) {
                    resourceLocks.remove(currentLock.path);
                    continue;
                }
                if ((currentLock.path.startsWith(lock.path)) && ((currentLock.isExclusive()) || (lock.isExclusive()))) {
                    // A child resource of this collection is locked
                    lockPaths.addElement(currentLock.path);
                }
            }
            if (!lockPaths.isEmpty()) {
                // One of the child paths was locked
                // We generate a multistatus error report
                Enumeration<String> lockPathsList = lockPaths.elements();
                resp.setStatus(WebdavStatus.SC_CONFLICT);
                XMLWriter generatedXML = new XMLWriter();
                generatedXML.writeXMLHeader();
                generatedXML.writeElement("D", DEFAULT_NAMESPACE, "multistatus", XMLWriter.OPENING);
                while (lockPathsList.hasMoreElements()) {
                    generatedXML.writeElement("D", "response", XMLWriter.OPENING);
                    generatedXML.writeElement("D", "href", XMLWriter.OPENING);
                    generatedXML.writeText(lockPathsList.nextElement());
                    generatedXML.writeElement("D", "href", XMLWriter.CLOSING);
                    generatedXML.writeElement("D", "status", XMLWriter.OPENING);
                    generatedXML.writeText("HTTP/1.1 " + WebdavStatus.SC_LOCKED + " " + WebdavStatus.getStatusText(WebdavStatus.SC_LOCKED));
                    generatedXML.writeElement("D", "status", XMLWriter.CLOSING);
                    generatedXML.writeElement("D", "response", XMLWriter.CLOSING);
                }
                generatedXML.writeElement("D", "multistatus", XMLWriter.CLOSING);
                Writer writer = resp.getWriter();
                writer.write(generatedXML.toString());
                writer.close();
                return;
            }
            boolean addLock = true;
            // Checking if there is already a shared lock on this path
            locksList = collectionLocks.elements();
            while (locksList.hasMoreElements()) {
                LockInfo currentLock = locksList.nextElement();
                if (currentLock.path.equals(lock.path)) {
                    if (currentLock.isExclusive()) {
                        resp.sendError(WebdavStatus.SC_LOCKED);
                        return;
                    } else {
                        if (lock.isExclusive()) {
                            resp.sendError(WebdavStatus.SC_LOCKED);
                            return;
                        }
                    }
                    currentLock.tokens.addElement(lockToken);
                    lock = currentLock;
                    addLock = false;
                }
            }
            if (addLock) {
                lock.tokens.addElement(lockToken);
                collectionLocks.addElement(lock);
            }
        } else {
            // Locking a single resource
            // Retrieving an already existing lock on that resource
            LockInfo presentLock = resourceLocks.get(lock.path);
            if (presentLock != null) {
                if ((presentLock.isExclusive()) || (lock.isExclusive())) {
                    // If either lock is exclusive, the lock can't be
                    // granted
                    resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
                    return;
                } else {
                    presentLock.tokens.addElement(lockToken);
                    lock = presentLock;
                }
            } else {
                lock.tokens.addElement(lockToken);
                resourceLocks.put(lock.path, lock);
                // Checking if a resource exists at this path
                exists = true;
                try {
                    object = resources.lookup(path);
                } catch (NamingException e) {
                    exists = false;
                }
                if (!exists) {
                    // "Creating" a lock-null resource
                    int slash = lock.path.lastIndexOf('/');
                    String parentPath = lock.path.substring(0, slash);
                    Vector<String> lockNulls = lockNullResources.get(parentPath);
                    if (lockNulls == null) {
                        lockNulls = new Vector<String>();
                        lockNullResources.put(parentPath, lockNulls);
                    }
                    lockNulls.addElement(lock.path);
                }
                // Add the Lock-Token header as by RFC 2518 8.10.1
                // - only do this for newly created locks
                resp.addHeader("Lock-Token", "<opaquelocktoken:" + lockToken + ">");
            }
        }
    }
    if (lockRequestType == LOCK_REFRESH) {
        String ifHeader = req.getHeader("If");
        if (ifHeader == null)
            ifHeader = "";
        // Checking resource locks
        LockInfo toRenew = resourceLocks.get(path);
        Enumeration<String> tokenList = null;
        if (toRenew != null) {
            // At least one of the tokens of the locks must have been given
            tokenList = toRenew.tokens.elements();
            while (tokenList.hasMoreElements()) {
                String token = tokenList.nextElement();
                if (ifHeader.indexOf(token) != -1) {
                    toRenew.expiresAt = lock.expiresAt;
                    lock = toRenew;
                }
            }
        }
        // Checking inheritable collection locks
        Enumeration<LockInfo> collectionLocksList = collectionLocks.elements();
        while (collectionLocksList.hasMoreElements()) {
            toRenew = collectionLocksList.nextElement();
            if (path.equals(toRenew.path)) {
                tokenList = toRenew.tokens.elements();
                while (tokenList.hasMoreElements()) {
                    String token = tokenList.nextElement();
                    if (ifHeader.indexOf(token) != -1) {
                        toRenew.expiresAt = lock.expiresAt;
                        lock = toRenew;
                    }
                }
            }
        }
    }
    // Set the status, then generate the XML response containing
    // the lock information
    XMLWriter generatedXML = new XMLWriter();
    generatedXML.writeXMLHeader();
    generatedXML.writeElement("D", DEFAULT_NAMESPACE, "prop", XMLWriter.OPENING);
    generatedXML.writeElement("D", "lockdiscovery", XMLWriter.OPENING);
    lock.toXML(generatedXML);
    generatedXML.writeElement("D", "lockdiscovery", XMLWriter.CLOSING);
    generatedXML.writeElement("D", "prop", XMLWriter.CLOSING);
    resp.setStatus(WebdavStatus.SC_OK);
    resp.setContentType("text/xml; charset=UTF-8");
    Writer writer = resp.getWriter();
    writer.write(generatedXML.toString());
    writer.close();
}
Also used : InputSource(org.xml.sax.InputSource) DOMWriter(org.apache.catalina.util.DOMWriter) Node(org.w3c.dom.Node) Element(org.w3c.dom.Element) NodeList(org.w3c.dom.NodeList) IOException(java.io.IOException) DirContext(javax.naming.directory.DirContext) Document(org.w3c.dom.Document) XMLWriter(org.apache.catalina.util.XMLWriter) SAXException(org.xml.sax.SAXException) StringWriter(java.io.StringWriter) DocumentBuilder(javax.xml.parsers.DocumentBuilder) NamingException(javax.naming.NamingException) Vector(java.util.Vector) XMLWriter(org.apache.catalina.util.XMLWriter) DOMWriter(org.apache.catalina.util.DOMWriter) StringWriter(java.io.StringWriter) Writer(java.io.Writer)

Example 2 with DOMWriter

use of org.apache.catalina.util.DOMWriter in project tomcat by apache.

the class WebdavStatus method doLock.

/**
 * LOCK Method.
 * @param req The Servlet request
 * @param resp The Servlet response
 * @throws ServletException If an error occurs
 * @throws IOException If an IO error occurs
 */
protected void doLock(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    if (readOnly) {
        resp.sendError(WebdavStatus.SC_FORBIDDEN);
        return;
    }
    if (isLocked(req)) {
        resp.sendError(WebdavStatus.SC_LOCKED);
        return;
    }
    LockInfo lock = new LockInfo(maxDepth);
    // Parsing lock request
    // Parsing depth header
    String depthStr = req.getHeader("Depth");
    if (depthStr == null) {
        lock.depth = maxDepth;
    } else {
        if (depthStr.equals("0")) {
            lock.depth = 0;
        } else {
            lock.depth = maxDepth;
        }
    }
    // Parsing timeout header
    int lockDuration = DEFAULT_TIMEOUT;
    String lockDurationStr = req.getHeader("Timeout");
    if (lockDurationStr == null) {
        lockDuration = DEFAULT_TIMEOUT;
    } else {
        int commaPos = lockDurationStr.indexOf(',');
        // If multiple timeouts, just use the first
        if (commaPos != -1) {
            lockDurationStr = lockDurationStr.substring(0, commaPos);
        }
        if (lockDurationStr.startsWith("Second-")) {
            lockDuration = Integer.parseInt(lockDurationStr.substring(7));
        } else {
            if (lockDurationStr.equalsIgnoreCase("infinity")) {
                lockDuration = MAX_TIMEOUT;
            } else {
                try {
                    lockDuration = Integer.parseInt(lockDurationStr);
                } catch (NumberFormatException e) {
                    lockDuration = MAX_TIMEOUT;
                }
            }
        }
        if (lockDuration == 0) {
            lockDuration = DEFAULT_TIMEOUT;
        }
        if (lockDuration > MAX_TIMEOUT) {
            lockDuration = MAX_TIMEOUT;
        }
    }
    lock.expiresAt = System.currentTimeMillis() + (lockDuration * 1000);
    int lockRequestType = LOCK_CREATION;
    Node lockInfoNode = null;
    DocumentBuilder documentBuilder = getDocumentBuilder();
    try {
        Document document = documentBuilder.parse(new InputSource(req.getInputStream()));
        // Get the root element of the document
        Element rootElement = document.getDocumentElement();
        lockInfoNode = rootElement;
    } catch (IOException | SAXException e) {
        lockRequestType = LOCK_REFRESH;
    }
    if (lockInfoNode != null) {
        // Reading lock information
        NodeList childList = lockInfoNode.getChildNodes();
        StringWriter strWriter = null;
        DOMWriter domWriter = null;
        Node lockScopeNode = null;
        Node lockTypeNode = null;
        Node lockOwnerNode = null;
        for (int i = 0; i < childList.getLength(); i++) {
            Node currentNode = childList.item(i);
            switch(currentNode.getNodeType()) {
                case Node.TEXT_NODE:
                    break;
                case Node.ELEMENT_NODE:
                    String nodeName = currentNode.getNodeName();
                    if (nodeName.endsWith("lockscope")) {
                        lockScopeNode = currentNode;
                    }
                    if (nodeName.endsWith("locktype")) {
                        lockTypeNode = currentNode;
                    }
                    if (nodeName.endsWith("owner")) {
                        lockOwnerNode = currentNode;
                    }
                    break;
            }
        }
        if (lockScopeNode != null) {
            childList = lockScopeNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        break;
                    case Node.ELEMENT_NODE:
                        String tempScope = currentNode.getNodeName();
                        if (tempScope.indexOf(':') != -1) {
                            lock.scope = tempScope.substring(tempScope.indexOf(':') + 1);
                        } else {
                            lock.scope = tempScope;
                        }
                        break;
                }
            }
            if (lock.scope == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            // Bad request
            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
        }
        if (lockTypeNode != null) {
            childList = lockTypeNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        break;
                    case Node.ELEMENT_NODE:
                        String tempType = currentNode.getNodeName();
                        if (tempType.indexOf(':') != -1) {
                            lock.type = tempType.substring(tempType.indexOf(':') + 1);
                        } else {
                            lock.type = tempType;
                        }
                        break;
                }
            }
            if (lock.type == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            // Bad request
            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
        }
        if (lockOwnerNode != null) {
            childList = lockOwnerNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        lock.owner += currentNode.getNodeValue();
                        break;
                    case Node.ELEMENT_NODE:
                        strWriter = new StringWriter();
                        domWriter = new DOMWriter(strWriter);
                        domWriter.print(currentNode);
                        lock.owner += strWriter.toString();
                        break;
                }
            }
            if (lock.owner == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            lock.owner = "";
        }
    }
    String path = getRelativePath(req);
    lock.path = path;
    WebResource resource = resources.getResource(path);
    Enumeration<LockInfo> locksList = null;
    if (lockRequestType == LOCK_CREATION) {
        // Generating lock id
        String lockTokenStr = req.getServletPath() + "-" + lock.type + "-" + lock.scope + "-" + req.getUserPrincipal() + "-" + lock.depth + "-" + lock.owner + "-" + lock.tokens + "-" + lock.expiresAt + "-" + System.currentTimeMillis() + "-" + secret;
        String lockToken = MD5Encoder.encode(ConcurrentMessageDigest.digestMD5(lockTokenStr.getBytes(StandardCharsets.ISO_8859_1)));
        if (resource.isDirectory() && lock.depth == maxDepth) {
            // Locking a collection (and all its member resources)
            // Checking if a child resource of this collection is
            // already locked
            Vector<String> lockPaths = new Vector<>();
            locksList = collectionLocks.elements();
            while (locksList.hasMoreElements()) {
                LockInfo currentLock = locksList.nextElement();
                if (currentLock.hasExpired()) {
                    resourceLocks.remove(currentLock.path);
                    continue;
                }
                if ((currentLock.path.startsWith(lock.path)) && ((currentLock.isExclusive()) || (lock.isExclusive()))) {
                    // A child collection of this collection is locked
                    lockPaths.addElement(currentLock.path);
                }
            }
            locksList = resourceLocks.elements();
            while (locksList.hasMoreElements()) {
                LockInfo currentLock = locksList.nextElement();
                if (currentLock.hasExpired()) {
                    resourceLocks.remove(currentLock.path);
                    continue;
                }
                if ((currentLock.path.startsWith(lock.path)) && ((currentLock.isExclusive()) || (lock.isExclusive()))) {
                    // A child resource of this collection is locked
                    lockPaths.addElement(currentLock.path);
                }
            }
            if (!lockPaths.isEmpty()) {
                // One of the child paths was locked
                // We generate a multistatus error report
                Enumeration<String> lockPathsList = lockPaths.elements();
                resp.setStatus(WebdavStatus.SC_CONFLICT);
                XMLWriter generatedXML = new XMLWriter();
                generatedXML.writeXMLHeader();
                generatedXML.writeElement("D", DEFAULT_NAMESPACE, "multistatus", XMLWriter.OPENING);
                while (lockPathsList.hasMoreElements()) {
                    generatedXML.writeElement("D", "response", XMLWriter.OPENING);
                    generatedXML.writeElement("D", "href", XMLWriter.OPENING);
                    generatedXML.writeText(lockPathsList.nextElement());
                    generatedXML.writeElement("D", "href", XMLWriter.CLOSING);
                    generatedXML.writeElement("D", "status", XMLWriter.OPENING);
                    generatedXML.writeText("HTTP/1.1 " + WebdavStatus.SC_LOCKED + " ");
                    generatedXML.writeElement("D", "status", XMLWriter.CLOSING);
                    generatedXML.writeElement("D", "response", XMLWriter.CLOSING);
                }
                generatedXML.writeElement("D", "multistatus", XMLWriter.CLOSING);
                Writer writer = resp.getWriter();
                writer.write(generatedXML.toString());
                writer.close();
                return;
            }
            boolean addLock = true;
            // Checking if there is already a shared lock on this path
            locksList = collectionLocks.elements();
            while (locksList.hasMoreElements()) {
                LockInfo currentLock = locksList.nextElement();
                if (currentLock.path.equals(lock.path)) {
                    if (currentLock.isExclusive()) {
                        resp.sendError(WebdavStatus.SC_LOCKED);
                        return;
                    } else {
                        if (lock.isExclusive()) {
                            resp.sendError(WebdavStatus.SC_LOCKED);
                            return;
                        }
                    }
                    currentLock.tokens.addElement(lockToken);
                    lock = currentLock;
                    addLock = false;
                }
            }
            if (addLock) {
                lock.tokens.addElement(lockToken);
                collectionLocks.addElement(lock);
            }
        } else {
            // Locking a single resource
            // Retrieving an already existing lock on that resource
            LockInfo presentLock = resourceLocks.get(lock.path);
            if (presentLock != null) {
                if ((presentLock.isExclusive()) || (lock.isExclusive())) {
                    // If either lock is exclusive, the lock can't be
                    // granted
                    resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
                    return;
                } else {
                    presentLock.tokens.addElement(lockToken);
                    lock = presentLock;
                }
            } else {
                lock.tokens.addElement(lockToken);
                resourceLocks.put(lock.path, lock);
                // Checking if a resource exists at this path
                if (!resource.exists()) {
                    // "Creating" a lock-null resource
                    int slash = lock.path.lastIndexOf('/');
                    String parentPath = lock.path.substring(0, slash);
                    Vector<String> lockNulls = lockNullResources.get(parentPath);
                    if (lockNulls == null) {
                        lockNulls = new Vector<>();
                        lockNullResources.put(parentPath, lockNulls);
                    }
                    lockNulls.addElement(lock.path);
                }
                // Add the Lock-Token header as by RFC 2518 8.10.1
                // - only do this for newly created locks
                resp.addHeader("Lock-Token", "<opaquelocktoken:" + lockToken + ">");
            }
        }
    }
    if (lockRequestType == LOCK_REFRESH) {
        String ifHeader = req.getHeader("If");
        if (ifHeader == null) {
            ifHeader = "";
        }
        // Checking resource locks
        LockInfo toRenew = resourceLocks.get(path);
        Enumeration<String> tokenList = null;
        if (toRenew != null) {
            // At least one of the tokens of the locks must have been given
            tokenList = toRenew.tokens.elements();
            while (tokenList.hasMoreElements()) {
                String token = tokenList.nextElement();
                if (ifHeader.contains(token)) {
                    toRenew.expiresAt = lock.expiresAt;
                    lock = toRenew;
                }
            }
        }
        // Checking inheritable collection locks
        Enumeration<LockInfo> collectionLocksList = collectionLocks.elements();
        while (collectionLocksList.hasMoreElements()) {
            toRenew = collectionLocksList.nextElement();
            if (path.equals(toRenew.path)) {
                tokenList = toRenew.tokens.elements();
                while (tokenList.hasMoreElements()) {
                    String token = tokenList.nextElement();
                    if (ifHeader.contains(token)) {
                        toRenew.expiresAt = lock.expiresAt;
                        lock = toRenew;
                    }
                }
            }
        }
    }
    // Set the status, then generate the XML response containing
    // the lock information
    XMLWriter generatedXML = new XMLWriter();
    generatedXML.writeXMLHeader();
    generatedXML.writeElement("D", DEFAULT_NAMESPACE, "prop", XMLWriter.OPENING);
    generatedXML.writeElement("D", "lockdiscovery", XMLWriter.OPENING);
    lock.toXML(generatedXML);
    generatedXML.writeElement("D", "lockdiscovery", XMLWriter.CLOSING);
    generatedXML.writeElement("D", "prop", XMLWriter.CLOSING);
    resp.setStatus(WebdavStatus.SC_OK);
    resp.setContentType("text/xml; charset=UTF-8");
    Writer writer = resp.getWriter();
    writer.write(generatedXML.toString());
    writer.close();
}
Also used : InputSource(org.xml.sax.InputSource) DOMWriter(org.apache.catalina.util.DOMWriter) Node(org.w3c.dom.Node) Element(org.w3c.dom.Element) NodeList(org.w3c.dom.NodeList) WebResource(org.apache.catalina.WebResource) IOException(java.io.IOException) Document(org.w3c.dom.Document) XMLWriter(org.apache.catalina.util.XMLWriter) SAXException(org.xml.sax.SAXException) StringWriter(java.io.StringWriter) DocumentBuilder(javax.xml.parsers.DocumentBuilder) Vector(java.util.Vector) XMLWriter(org.apache.catalina.util.XMLWriter) DOMWriter(org.apache.catalina.util.DOMWriter) StringWriter(java.io.StringWriter) Writer(java.io.Writer)

Example 3 with DOMWriter

use of org.apache.catalina.util.DOMWriter in project Payara by payara.

the class WebdavStatus method doLock.

/**
 * LOCK Method.
 */
protected void doLock(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    if (readOnly) {
        resp.sendError(WebdavStatus.SC_FORBIDDEN);
        return;
    }
    if (isLocked(req)) {
        resp.sendError(WebdavStatus.SC_LOCKED);
        return;
    }
    LockInfo lock = new LockInfo();
    // Parsing lock request
    // Parsing depth header
    String depthStr = req.getHeader("Depth");
    if (depthStr == null) {
        lock.depth = INFINITY;
    } else {
        if ("0".equals(depthStr)) {
            lock.depth = 0;
        } else {
            lock.depth = INFINITY;
        }
    }
    // Parsing timeout header
    int lockDuration = DEFAULT_TIMEOUT;
    String lockDurationStr = req.getHeader("Timeout");
    if (lockDurationStr == null) {
        lockDuration = DEFAULT_TIMEOUT;
    } else {
        int commaPos = lockDurationStr.indexOf(",");
        // If multiple timeouts, just use the first
        if (commaPos != -1) {
            lockDurationStr = lockDurationStr.substring(0, commaPos);
        }
        if (lockDurationStr.startsWith("Second-")) {
            lockDuration = Integer.parseInt(lockDurationStr.substring(7));
        } else {
            if ("infinity".equalsIgnoreCase(lockDurationStr)) {
                lockDuration = MAX_TIMEOUT;
            } else {
                try {
                    lockDuration = Integer.parseInt(lockDurationStr);
                } catch (NumberFormatException e) {
                    lockDuration = MAX_TIMEOUT;
                }
            }
        }
        if (lockDuration == 0) {
            lockDuration = DEFAULT_TIMEOUT;
        }
        if (lockDuration > MAX_TIMEOUT) {
            lockDuration = MAX_TIMEOUT;
        }
    }
    lock.expiresAt = System.currentTimeMillis() + lockDuration * 1000L;
    int lockRequestType = LOCK_CREATION;
    Node lockInfoNode = null;
    DocumentBuilder documentBuilder = getDocumentBuilder();
    try {
        Document document = documentBuilder.parse(new InputSource(req.getInputStream()));
        // Get the root element of the document
        Element rootElement = document.getDocumentElement();
        lockInfoNode = rootElement;
    } catch (IOException | SAXException e) {
        lockRequestType = LOCK_REFRESH;
    }
    if (lockInfoNode != null) {
        // Reading lock information
        NodeList childList = lockInfoNode.getChildNodes();
        StringWriter strWriter = null;
        DOMWriter domWriter = null;
        Node lockScopeNode = null;
        Node lockTypeNode = null;
        Node lockOwnerNode = null;
        for (int i = 0; i < childList.getLength(); i++) {
            Node currentNode = childList.item(i);
            switch(currentNode.getNodeType()) {
                case Node.TEXT_NODE:
                    break;
                case Node.ELEMENT_NODE:
                    String nodeName = currentNode.getNodeName();
                    if (nodeName.endsWith("lockscope")) {
                        lockScopeNode = currentNode;
                    }
                    if (nodeName.endsWith("locktype")) {
                        lockTypeNode = currentNode;
                    }
                    if (nodeName.endsWith("owner")) {
                        lockOwnerNode = currentNode;
                    }
                    break;
                default:
                    break;
            }
        }
        if (lockScopeNode != null) {
            childList = lockScopeNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        break;
                    case Node.ELEMENT_NODE:
                        String tempScope = currentNode.getNodeName();
                        if (tempScope.indexOf(':') != -1) {
                            lock.scope = tempScope.substring(tempScope.indexOf(':') + 1);
                        } else {
                            lock.scope = tempScope;
                        }
                        break;
                    default:
                        break;
                }
            }
            if (lock.scope == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            // Bad request
            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
        }
        if (lockTypeNode != null) {
            childList = lockTypeNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        break;
                    case Node.ELEMENT_NODE:
                        String tempType = currentNode.getNodeName();
                        if (tempType.indexOf(':') != -1) {
                            lock.type = tempType.substring(tempType.indexOf(':') + 1);
                        } else {
                            lock.type = tempType;
                        }
                        break;
                    default:
                        break;
                }
            }
            if (lock.type == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            // Bad request
            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
        }
        if (lockOwnerNode != null) {
            childList = lockOwnerNode.getChildNodes();
            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                switch(currentNode.getNodeType()) {
                    case Node.TEXT_NODE:
                        lock.owner += currentNode.getNodeValue();
                        break;
                    case Node.ELEMENT_NODE:
                        strWriter = new StringWriter();
                        domWriter = new DOMWriter(strWriter, true);
                        domWriter.setQualifiedNames(false);
                        domWriter.print(currentNode);
                        lock.owner += strWriter.toString();
                        break;
                    default:
                        break;
                }
            }
            if (lock.owner == null) {
                // Bad request
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
            }
        } else {
            lock.owner = "";
        }
    }
    String path = getRelativePath(req);
    lock.path = path;
    boolean exists = true;
    Object object = null;
    try {
        object = resources.lookup(path);
    } catch (NamingException e) {
        exists = false;
    }
    if (lockRequestType == LOCK_CREATION) {
        // Generating lock id
        String lockTokenStr = req.getServletPath() + "-" + lock.type + "-" + lock.scope + "-" + req.getUserPrincipal() + "-" + lock.depth + "-" + lock.owner + "-" + lock.tokens + "-" + lock.expiresAt + "-" + System.currentTimeMillis() + "-" + secret;
        byte[] digestBytes = null;
        synchronized (md5Helper) {
            digestBytes = md5Helper.digest(lockTokenStr.getBytes(Charset.defaultCharset()));
        }
        String lockToken = new String(md5Encoder.encode(digestBytes));
        if (exists && object instanceof DirContext && lock.depth == INFINITY) {
            // Locking a collection (and all its member resources)
            // Checking if a child resource of this collection is
            // already locked
            List<String> lockPaths = new ArrayList<>();
            for (LockInfo currentLock : collectionLocks) {
                if (currentLock.hasExpired()) {
                    resourceLocks.remove(currentLock.path);
                    continue;
                }
                if (currentLock.path.startsWith(lock.path) && (currentLock.isExclusive() || lock.isExclusive())) {
                    // A child collection of this collection is locked
                    lockPaths.add(currentLock.path);
                }
            }
            Iterator<Map.Entry<String, LockInfo>> resourceLockIterator = resourceLocks.entrySet().iterator();
            while (resourceLockIterator.hasNext()) {
                Map.Entry<String, LockInfo> entry = resourceLockIterator.next();
                LockInfo currentLock = entry.getValue();
                if (currentLock.hasExpired()) {
                    resourceLockIterator.remove();
                    continue;
                }
                if (currentLock.path.startsWith(lock.path) && (currentLock.isExclusive() || lock.isExclusive())) {
                    // A child resource of this collection is locked
                    lockPaths.add(currentLock.path);
                }
            }
            if (!lockPaths.isEmpty()) {
                // One of the child paths was locked
                // We generate a multistatus error report
                resp.setStatus(WebdavStatus.SC_CONFLICT);
                XMLWriter generatedXML = new XMLWriter();
                generatedXML.writeXMLHeader();
                generatedXML.writeElement(null, "multistatus" + generateNamespaceDeclarations(), XMLWriter.OPENING);
                for (String lockPath : lockPaths) {
                    generatedXML.writeElement(null, "response", XMLWriter.OPENING);
                    generatedXML.writeElement(null, "href", XMLWriter.OPENING);
                    generatedXML.writeText(lockPath);
                    generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
                    generatedXML.writeElement(null, "status", XMLWriter.OPENING);
                    generatedXML.writeText("HTTP/1.1 " + WebdavStatus.SC_LOCKED + " " + WebdavStatus.getStatusText(WebdavStatus.SC_LOCKED));
                    generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
                    generatedXML.writeElement(null, "response", XMLWriter.CLOSING);
                }
                generatedXML.writeElement(null, "multistatus", XMLWriter.CLOSING);
                Writer writer = resp.getWriter();
                writer.write(generatedXML.toString());
                writer.close();
                return;
            }
            boolean addLock = true;
            // Checking if there is already a shared lock on this path
            for (LockInfo currentLock : collectionLocks) {
                if (currentLock.path.equals(lock.path)) {
                    if (currentLock.isExclusive()) {
                        resp.sendError(WebdavStatus.SC_LOCKED);
                        return;
                    } else {
                        if (lock.isExclusive()) {
                            resp.sendError(WebdavStatus.SC_LOCKED);
                            return;
                        }
                    }
                    currentLock.tokens.add(lockToken);
                    lock = currentLock;
                    addLock = false;
                }
            }
            if (addLock) {
                lock.tokens.add(lockToken);
                collectionLocks.add(lock);
            }
        } else {
            // Locking a single resource
            // Retrieving an already existing lock on that resource
            LockInfo presentLock = resourceLocks.get(lock.path);
            if (presentLock != null) {
                if (presentLock.isExclusive() || lock.isExclusive()) {
                    // If either lock is exclusive, the lock can't be
                    // granted
                    resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
                    return;
                } else {
                    presentLock.tokens.add(lockToken);
                    lock = presentLock;
                }
            } else {
                lock.tokens.add(lockToken);
                resourceLocks.put(lock.path, lock);
                // Checking if a resource exists at this path
                exists = true;
                try {
                    object = resources.lookup(path);
                } catch (NamingException e) {
                    exists = false;
                }
                if (!exists) {
                    // "Creating" a lock-null resource
                    int slash = lock.path.lastIndexOf('/');
                    String parentPath = lock.path.substring(0, slash);
                    List<String> lockNulls = lockNullResources.get(parentPath);
                    if (lockNulls == null) {
                        lockNulls = new CopyOnWriteArrayList<>();
                        lockNullResources.put(parentPath, lockNulls);
                    }
                    lockNulls.add(lock.path);
                }
                // Add the Lock-Token header as by RFC 2518 8.10.1
                // - only do this for newly created locks
                resp.addHeader("Lock-Token", "<opaquelocktoken:" + lockToken + ">");
            }
        }
    }
    if (lockRequestType == LOCK_REFRESH) {
        String ifHeader = req.getHeader("If");
        if (ifHeader == null)
            ifHeader = "";
        // Checking resource locks
        LockInfo toRenew = resourceLocks.get(path);
        if (lock != null) {
            // At least one of the tokens of the locks must have been given
            for (String token : toRenew.tokens) {
                if (ifHeader.contains(token)) {
                    toRenew.expiresAt = lock.expiresAt;
                    lock = toRenew;
                }
            }
        }
        // Checking inheritable collection locks
        for (LockInfo collectionLock : collectionLocks) {
            toRenew = collectionLock;
            if (path.equals(toRenew.path)) {
                for (String token : toRenew.tokens) {
                    if (ifHeader.contains(token)) {
                        toRenew.expiresAt = lock.expiresAt;
                        lock = toRenew;
                    }
                }
            }
        }
    }
    // Set the status, then generate the XML response containing
    // the lock information
    XMLWriter generatedXML = new XMLWriter();
    generatedXML.writeXMLHeader();
    generatedXML.writeElement(null, "prop" + generateNamespaceDeclarations(), XMLWriter.OPENING);
    generatedXML.writeElement(null, "lockdiscovery", XMLWriter.OPENING);
    lock.toXML(generatedXML);
    generatedXML.writeElement(null, "lockdiscovery", XMLWriter.CLOSING);
    generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
    resp.setStatus(WebdavStatus.SC_OK);
    resp.setContentType("text/xml; charset=UTF-8");
    try (Writer writer = resp.getWriter()) {
        writer.write(generatedXML.toString());
    }
}
Also used : InputSource(org.xml.sax.InputSource) Node(org.w3c.dom.Node) Element(org.w3c.dom.Element) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) DirContext(javax.naming.directory.DirContext) Document(org.w3c.dom.Document) XMLWriter(org.apache.catalina.util.XMLWriter) SAXException(org.xml.sax.SAXException) CacheEntry(org.apache.naming.resources.CacheEntry) StringWriter(java.io.StringWriter) NamingException(javax.naming.NamingException) DOMWriter(org.apache.catalina.util.DOMWriter) NodeList(org.w3c.dom.NodeList) IOException(java.io.IOException) DocumentBuilder(javax.xml.parsers.DocumentBuilder) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) XMLWriter(org.apache.catalina.util.XMLWriter) DOMWriter(org.apache.catalina.util.DOMWriter) StringWriter(java.io.StringWriter) Writer(java.io.Writer)

Aggregations

IOException (java.io.IOException)3 StringWriter (java.io.StringWriter)3 Writer (java.io.Writer)3 DocumentBuilder (javax.xml.parsers.DocumentBuilder)3 DOMWriter (org.apache.catalina.util.DOMWriter)3 XMLWriter (org.apache.catalina.util.XMLWriter)3 Document (org.w3c.dom.Document)3 Element (org.w3c.dom.Element)3 Node (org.w3c.dom.Node)3 NodeList (org.w3c.dom.NodeList)3 InputSource (org.xml.sax.InputSource)3 SAXException (org.xml.sax.SAXException)3 Vector (java.util.Vector)2 NamingException (javax.naming.NamingException)2 DirContext (javax.naming.directory.DirContext)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 WebResource (org.apache.catalina.WebResource)1 CacheEntry (org.apache.naming.resources.CacheEntry)1