From 3dfdf48af479f836f942d27c44b293469c646615 Mon Sep 17 00:00:00 2001 From: Gavin Cornwell Date: Wed, 27 Jan 2010 12:13:56 +0000 Subject: [PATCH] Merged V3.2 to HEAD 17891: Merged DEV_TEMPORARY to V3.2 17873: ETHREEOH-3810: WCM - Recursion detector erroring 18032: Merged V3.1 to V3.2 18030: Merged V2.2 to V3.1 17683: Merged DEV_TEMPORARY to V2.2 (back-port of fix) 17677: ETHREEOH-2778: davfs2 is not working correctly with Alfresco 17880: Merged DEV_TEMPORARY to V2.2 (record-only as fix is already applied to 3.1 branch) 17845: ETWOTWO-1289: My Web Files (Forms) dashlets: XSS Attck can be made when web project's details has been edited 18062: Merged DEV_TEMPORARY to V3.2 18036: ETHREEOH-1844: Text field (areas) became non-editable if user use navigate-remove combination for repeatable elements on Create Web content based on web form screen 18205: Merged V3.1 to V3.2 (record-only) *RECORD ONLY* Merged DEV/TEMPORARY to 3.1 17837: ETHREEOH-3801: Creating users via the api does not add them to the user store 18277: Merged DEV_TEMPORARY to V3.2 18178: ETHREEOH-3222: ERROR [org.alfresco.webdav.protocol] WebDAV method not implemented - PROPPATCH 18311: Fix for ETHREEOH-3872: forms32 examples not working 18317: Remaining fixes to forms samples (ETHREEOH-3872) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18318 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/repo/webdav/LockMethod.java | 124 +++++- .../alfresco/repo/webdav/PropFindMethod.java | 2 +- .../alfresco/repo/webdav/PropPatchMethod.java | 396 ++++++++++++++++++ .../java/org/alfresco/repo/webdav/WebDAV.java | 11 + .../alfresco/repo/webdav/WebDAVProperty.java | 27 ++ .../alfresco/repo/webdav/WebDAVServlet.java | 1 + 6 files changed, 558 insertions(+), 3 deletions(-) create mode 100755 source/java/org/alfresco/repo/webdav/PropPatchMethod.java diff --git a/source/java/org/alfresco/repo/webdav/LockMethod.java b/source/java/org/alfresco/repo/webdav/LockMethod.java index 0d64652bd8..6e1df580a6 100644 --- a/source/java/org/alfresco/repo/webdav/LockMethod.java +++ b/source/java/org/alfresco/repo/webdav/LockMethod.java @@ -24,6 +24,9 @@ */ package org.alfresco.repo.webdav; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -37,7 +40,10 @@ import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileNotFoundException; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.dom4j.DocumentHelper; import org.dom4j.io.XMLWriter; +import org.xml.sax.Attributes; /** * Implements the WebDAV LOCK method @@ -46,6 +52,8 @@ import org.dom4j.io.XMLWriter; */ public class LockMethod extends WebDAVMethod { + public static final String EMPTY_NS = ""; + private String m_strLockToken = null; private int m_timeoutDuration = WebDAV.DEPTH_INFINITY; @@ -232,6 +240,9 @@ public class LockMethod extends WebDAVMethod createLock(lockNodeInfo.getNodeRef(), userName); } + m_response.setHeader(WebDAV.HEADER_LOCK_TOKEN, "<" + WebDAV.makeLockToken(lockNodeInfo.getNodeRef(), userName) + ">"); + m_response.setHeader(WebDAV.HEADER_CONTENT_TYPE, WebDAV.XML_CONTENT_TYPE); + // We either created a new lock or refreshed an existing lock, send back the lock details generateResponse(lockNodeInfo.getNodeRef(), userName); } @@ -302,16 +313,125 @@ public class LockMethod extends WebDAVMethod xml.startDocument(); String nsdec = generateNamespaceDeclarations(null); - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_MULTI_STATUS + nsdec, WebDAV.XML_NS_MULTI_STATUS + nsdec, + xml.startElement(EMPTY_NS, WebDAV.XML_PROP + nsdec, WebDAV.XML_PROP + nsdec, getDAVHelper().getNullAttributes()); // Output the lock details generateLockDiscoveryXML(xml, lockNode); // Close off the XML - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_MULTI_STATUS, WebDAV.XML_NS_MULTI_STATUS); + xml.endElement(EMPTY_NS, WebDAV.XML_PROP, WebDAV.XML_PROP); // Send the XML back to the client xml.flush(); } + + + /** + * Generates the lock discovery XML response + * + * @param xml XMLWriter + * @param lockNode NodeRef + */ + protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode) throws Exception + { + Attributes nullAttr= getDAVHelper().getNullAttributes(); + + if (lockNode != null) + { + + // Get the lock details + + NodeService nodeService = getNodeService(); + + String owner = (String) nodeService.getProperty(lockNode, ContentModel.PROP_LOCK_OWNER); + Date expiryDate = (Date) nodeService.getProperty(lockNode, ContentModel.PROP_EXPIRY_DATE); + + // Output the XML response + + xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_DISCOVERY, WebDAV.XML_LOCK_DISCOVERY, nullAttr); + xml.startElement(EMPTY_NS, WebDAV.XML_ACTIVE_LOCK, WebDAV.XML_ACTIVE_LOCK, nullAttr); + + xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_LOCK_TYPE, nullAttr); + xml.write(DocumentHelper.createElement(WebDAV.XML_WRITE)); + xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_LOCK_TYPE); + + // NOTE: We only do exclusive lock tokens at the moment + + xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_LOCK_SCOPE, nullAttr); + xml.write(DocumentHelper.createElement(WebDAV.XML_EXCLUSIVE)); + xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_LOCK_SCOPE); + + // NOTE: We only support one level of lock at the moment + + xml.startElement(EMPTY_NS, WebDAV.XML_DEPTH, WebDAV.XML_DEPTH, nullAttr); + xml.write(WebDAV.ZERO); + xml.endElement(EMPTY_NS, WebDAV.XML_DEPTH, WebDAV.XML_DEPTH); + + xml.startElement(EMPTY_NS, WebDAV.XML_OWNER, WebDAV.XML_OWNER, nullAttr); + xml.write(owner); + xml.endElement(EMPTY_NS, WebDAV.XML_OWNER, WebDAV.XML_OWNER); + + xml.startElement(EMPTY_NS, WebDAV.XML_TIMEOUT, WebDAV.XML_TIMEOUT, nullAttr); + + // Output the expiry time + + String strTimeout = WebDAV.INFINITE; + if (expiryDate != null) + { + long timeoutRemaining = (expiryDate.getTime() - System.currentTimeMillis())/1000L; + + strTimeout = WebDAV.SECOND + timeoutRemaining; + } + xml.write(strTimeout); + + xml.endElement(EMPTY_NS, WebDAV.XML_TIMEOUT, WebDAV.XML_TIMEOUT); + + xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_LOCK_TOKEN, nullAttr); + xml.startElement(EMPTY_NS, WebDAV.XML_HREF, WebDAV.XML_HREF, nullAttr); + + xml.write(WebDAV.makeLockToken(lockNode, owner)); + + xml.endElement(EMPTY_NS, WebDAV.XML_HREF, WebDAV.XML_HREF); + xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_LOCK_TOKEN); + + xml.endElement(EMPTY_NS, WebDAV.XML_ACTIVE_LOCK, WebDAV.XML_ACTIVE_LOCK); + xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_DISCOVERY, WebDAV.XML_LOCK_DISCOVERY); + } + } + + /** + * Generates a list of namespace declarations for the response + */ + protected String generateNamespaceDeclarations(HashMap nameSpaces) + { + StringBuilder ns = new StringBuilder(); + + ns.append(" "); + ns.append(WebDAV.XML_NS); + ns.append("=\""); + ns.append(WebDAV.DEFAULT_NAMESPACE_URI); + ns.append("\""); + + // Add additional namespaces + + if ( nameSpaces != null) + { + Iterator namespaceList = nameSpaces.keySet().iterator(); + + while (namespaceList.hasNext()) + { + String strNamespaceUri = namespaceList.next(); + String strNamespaceName = nameSpaces.get(strNamespaceUri); + + ns.append(" ").append(WebDAV.XML_NS).append(":").append(strNamespaceName).append("=\""); + ns.append(strNamespaceUri).append("\" "); + } + } + + return ns.toString(); + } + + + } diff --git a/source/java/org/alfresco/repo/webdav/PropFindMethod.java b/source/java/org/alfresco/repo/webdav/PropFindMethod.java index a24b2e287f..76683a3093 100644 --- a/source/java/org/alfresco/repo/webdav/PropFindMethod.java +++ b/source/java/org/alfresco/repo/webdav/PropFindMethod.java @@ -348,7 +348,7 @@ public class PropFindMethod extends WebDAVMethod /** * Creates a WebDAVProperty from the given XML node */ - private WebDAVProperty createProperty(Node node) + protected WebDAVProperty createProperty(Node node) { WebDAVProperty property = null; diff --git a/source/java/org/alfresco/repo/webdav/PropPatchMethod.java b/source/java/org/alfresco/repo/webdav/PropPatchMethod.java new file mode 100755 index 0000000000..718b859fc0 --- /dev/null +++ b/source/java/org/alfresco/repo/webdav/PropPatchMethod.java @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.webdav; + +import java.util.ArrayList; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.dom4j.DocumentHelper; +import org.dom4j.io.XMLWriter; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.Attributes; + +/** + * Implements the WebDAV PROPPATCH method + * + * @author Ivan Rybnikov + */ +public class PropPatchMethod extends PropFindMethod +{ + + // Properties to patch + protected ArrayList m_propertyActions = null; + + @Override + protected void executeImpl() throws WebDAVServerException, Exception + { + + m_response.setStatus(WebDAV.WEBDAV_SC_MULTI_STATUS); + + FileInfo pathNodeInfo = null; + try + { + // Check that the path exists + pathNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), m_strPath, m_request.getServletPath()); + } + catch (FileNotFoundException e) + { + // The path is not valid - send a 404 error back to the client + throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND); + } + + // Set the response content type + m_response.setContentType(WebDAV.XML_CONTENT_TYPE); + + // Create multistatus response + XMLWriter xml = createXMLWriter(); + + xml.startDocument(); + + String nsdec = generateNamespaceDeclarations(m_namespaces); + xml.startElement( + WebDAV.DAV_NS, + WebDAV.XML_MULTI_STATUS + nsdec, + WebDAV.XML_NS_MULTI_STATUS + nsdec, + getDAVHelper().getNullAttributes()); + + // Create the path for the current location in the tree + StringBuilder baseBuild = new StringBuilder(256); + baseBuild.append(getPath()); + if (baseBuild.length() == 0 || baseBuild.charAt(baseBuild.length() - 1) != WebDAVHelper.PathSeperatorChar) + { + baseBuild.append(WebDAVHelper.PathSeperatorChar); + } + String basePath = baseBuild.toString(); + + // Output the response for the root node, depth zero + generateResponse(xml, pathNodeInfo, basePath); + + // Close the outer XML element + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_MULTI_STATUS, WebDAV.XML_NS_MULTI_STATUS); + + // Send remaining data + xml.flush(); + } + + /** + * Parse the request body + * + * @exception WebDAVServerException + */ + @Override + protected void parseRequestBody() throws WebDAVServerException + { + Document body = getRequestBodyAsDocument(); + if (body != null) + { + Element rootElement = body.getDocumentElement(); + NodeList childList = rootElement.getChildNodes(); + + m_propertyActions = new ArrayList(); + + 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: + if (currentNode.getNodeName().endsWith(WebDAV.XML_SET) || currentNode.getNodeName().endsWith(WebDAV.XML_REMOVE)) + { + NodeList propertiesList = currentNode.getChildNodes(); + + for (int j = 0; j < propertiesList.getLength(); j++) + { + Node propertiesNode = propertiesList.item(j); + switch (propertiesNode.getNodeType()) + { + case Node.TEXT_NODE: + break; + case Node.ELEMENT_NODE: + if (propertiesNode.getNodeName().endsWith(WebDAV.XML_PROP)) + { + NodeList propList = propertiesNode.getChildNodes(); + + for (int k = 0; k < propList.getLength(); k++) + { + Node propNode = propList.item(k); + switch (propNode.getNodeType()) + { + case Node.TEXT_NODE: + break; + case Node.ELEMENT_NODE: + int action = currentNode.getNodeName().endsWith(WebDAV.XML_SET) ? PropertyAction.SET : PropertyAction.REMOVE; + m_propertyActions.add(new PropertyAction(action, createProperty(propNode))); + break; + } + } + } + break; + } + } + } + break; + } + } + + } + + } + + /** + * Parse the request headers + * + * @exception WebDAVServerException + */ + @Override + protected void parseRequestHeaders() throws WebDAVServerException + { + // Nothing to do in this method + } + + /** + * Creates a WebDAVProperty from the given XML node + */ + protected WebDAVProperty createProperty(Node node) + { + WebDAVProperty property = super.createProperty(node); + + String strValue = null; + Node value = node.getFirstChild(); + if (value != null) + { + strValue = value.getNodeValue(); + } + property.setValue(strValue); + + return property; + } + + + + + /** + * Generates the required response XML + * + * @param xml XMLWriter + * @param node NodeRef + * @param path String + */ + protected void generateResponse(XMLWriter xml, FileInfo nodeInfo, String path) throws Exception + { + boolean isFolder = nodeInfo.isFolder(); + + // Output the response block for the current node + xml.startElement( + WebDAV.DAV_NS, + WebDAV.XML_RESPONSE, + WebDAV.XML_NS_RESPONSE, + getDAVHelper().getNullAttributes()); + + // Build the href string for the current node + String strHRef = WebDAV.getURLForPath(m_request, path, isFolder); + + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF, getDAVHelper().getNullAttributes()); + xml.write(strHRef); + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF); + + + boolean failed = false; + WebDAVProperty failedProperty = null; + for (PropertyAction action : m_propertyActions) + { + if (action.getProperty().isProtected()) + { + generateError(xml); + failed = true; + failedProperty = action.getProperty(); + break; + } + } + + for (PropertyAction propertyAction : m_propertyActions) + { + int statusCode; + String statusCodeDescription; + WebDAVProperty property = propertyAction.getProperty(); + + if (!failed) + { + if (PropertyAction.SET == propertyAction.getAction()) + { + getNodeService().setProperty(nodeInfo.getNodeRef(), property.createQName(), property.getValue()); + } + else if (PropertyAction.REMOVE == propertyAction.getAction()) + { + getNodeService().removeProperty(nodeInfo.getNodeRef(), property.createQName()); + } + else + { + throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST); + } + statusCode = HttpServletResponse.SC_OK; + statusCodeDescription = WebDAV.SC_OK_DESC; + } + else if (failedProperty == property) + { + statusCode = HttpServletResponse.SC_FORBIDDEN; + statusCodeDescription = WebDAV.SC_FORBIDDEN_DESC; + } + else + { + statusCode = WebDAV.WEBDAV_SC_FAILED_DEPENDENCY; + statusCodeDescription = WebDAV.WEBDAV_SC_FAILED_DEPENDENCY_DESC; + } + + generatePropertyResponse(xml, property, statusCode, statusCodeDescription); + } + + // Close off the response element + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_RESPONSE, WebDAV.XML_NS_RESPONSE); + } + + + + /** + * Generates the XML response for a PROPFIND request that asks for a list of + * all known properties + * + * @param xml XMLWriter + * @param node NodeRef + * @param isDir boolean + */ + protected void generatePropertyResponse(XMLWriter xml, WebDAVProperty property, int status, String description) + { + try + { + // Output the start of the properties element + Attributes nullAttr = getDAVHelper().getNullAttributes(); + + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr); + + // Output property name + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr); + if (property.hasNamespaceName()) + { + xml.write(DocumentHelper.createElement(property.getNamespaceName() + WebDAV.NAMESPACE_SEPARATOR + property.getName())); + } + else + { + xml.write(DocumentHelper.createElement(property.getName())); + } + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP); + + // Output action result status + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr); + xml.write(WebDAV.HTTP1_1 + " " + status + " " + description); + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS); + + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT); + } + catch (Exception ex) + { + // Convert to a runtime exception + throw new AlfrescoRuntimeException("XML processing error", ex); + } + } + + + /** + * Generates the error tag + * + * @param xml XMLWriter + */ + protected void generateError(XMLWriter xml) + { + try + { + // Output the start of the error element + Attributes nullAttr = getDAVHelper().getNullAttributes(); + + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_ERROR, WebDAV.XML_NS_ERROR, nullAttr); + // Output error + xml.write(DocumentHelper.createElement(WebDAV.XML_NS_CANNOT_MODIFY_PROTECTED_PROPERTY)); + + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_ERROR, WebDAV.XML_NS_ERROR); + } + catch (Exception ex) + { + // Convert to a runtime exception + throw new AlfrescoRuntimeException("XML processing error", ex); + } + } + + + private class PropertyAction + { + protected static final int SET = 0; + protected static final int REMOVE = 1; + + private WebDAVProperty property; + private int action; + + public PropertyAction(int action, WebDAVProperty property) + { + this.action = action; + this.property = property; + } + + public int getAction() + { + return action; + } + + public WebDAVProperty getProperty() + { + return property; + } + + public String toString() + { + StringBuilder str = new StringBuilder(); + + str.append("["); + str.append("action="); + str.append(getAction() == 0 ? "SET" : "REMOVE"); + str.append(",property="); + str.append(getProperty()); + str.append("]"); + + return str.toString(); + } + } + + +} diff --git a/source/java/org/alfresco/repo/webdav/WebDAV.java b/source/java/org/alfresco/repo/webdav/WebDAV.java index dabd9e150e..07a744f553 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAV.java +++ b/source/java/org/alfresco/repo/webdav/WebDAV.java @@ -71,11 +71,17 @@ public class WebDAV public static final int WEBDAV_SC_MULTI_STATUS = 207; public static final int WEBDAV_SC_LOCKED = 423; + public static final int WEBDAV_SC_FAILED_DEPENDENCY = 424; + + // WebDAV HTTP response code descriptions + + public static final String WEBDAV_SC_FAILED_DEPENDENCY_DESC = "Failed Dependency"; // HTTP response code descriptions public static final String SC_OK_DESC = "OK"; public static final String SC_NOT_FOUND_DESC = "Not Found"; + public static final String SC_FORBIDDEN_DESC = "Forbidden"; // HTTP methods @@ -169,6 +175,9 @@ public class WebDAV public static final String XML_SUPPORTED_LOCK = "supportedlock"; public static final String XML_TIMEOUT = "timeout"; public static final String XML_WRITE = "write"; + public static final String XML_SET = "set"; + public static final String XML_REMOVE = "remove"; + public static final String XML_ERROR = "error"; // Namespaced versions of payload elements @@ -202,6 +211,8 @@ public class WebDAV public static final String XML_NS_SUPPORTED_LOCK = DAV_NS_PREFIX + "supportedlock"; public static final String XML_NS_TIMEOUT = DAV_NS_PREFIX + "timeout"; public static final String XML_NS_WRITE = DAV_NS_PREFIX + "write"; + public static final String XML_NS_ERROR = DAV_NS_PREFIX + "error"; + public static final String XML_NS_CANNOT_MODIFY_PROTECTED_PROPERTY = DAV_NS_PREFIX + "cannot-modify-protected-property"; public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8"; diff --git a/source/java/org/alfresco/repo/webdav/WebDAVProperty.java b/source/java/org/alfresco/repo/webdav/WebDAVProperty.java index de9704e0dd..9a934765bc 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAVProperty.java +++ b/source/java/org/alfresco/repo/webdav/WebDAVProperty.java @@ -24,6 +24,8 @@ */ package org.alfresco.repo.webdav; +import org.alfresco.service.namespace.QName; + /** * Class to represent a WebDAV property * @@ -136,6 +138,31 @@ public class WebDAVProperty m_strValue = strValue; } + /** + * Creates QName of the property + * + * @return QName + */ + public QName createQName() + { + return QName.createQName(m_strNamespaceUri, m_strName); + } + + /** + * Returns true if property is protected according to the WebDav specification + * + * @return boolean + */ + public boolean isProtected() + { + return WebDAV.XML_GET_CONTENT_LENGTH.equals(m_strName) || + WebDAV.XML_GET_ETAG.equals(m_strName) || + WebDAV.XML_GET_LAST_MODIFIED.equals(m_strName) || + WebDAV.XML_LOCK_DISCOVERY.equals(m_strName) || + WebDAV.XML_RESOURCE_TYPE.equals(m_strName) || + WebDAV.XML_SUPPORTED_LOCK.equals(m_strName); + } + /** * Return the property as a string * diff --git a/source/java/org/alfresco/repo/webdav/WebDAVServlet.java b/source/java/org/alfresco/repo/webdav/WebDAVServlet.java index acecb7bcff..1483a5f7c5 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAVServlet.java +++ b/source/java/org/alfresco/repo/webdav/WebDAVServlet.java @@ -304,6 +304,7 @@ public class WebDAVServlet extends HttpServlet m_davMethods = new Hashtable(); m_davMethods.put(WebDAV.METHOD_PROPFIND, PropFindMethod.class); + m_davMethods.put(WebDAV.METHOD_PROPPATCH, PropPatchMethod.class); m_davMethods.put(WebDAV.METHOD_COPY, CopyMethod.class); m_davMethods.put(WebDAV.METHOD_DELETE, DeleteMethod.class); m_davMethods.put(WebDAV.METHOD_GET, GetMethod.class);