diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/authority.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/authority.lib.ftl index 139340ce37..94437b2e66 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/authority.lib.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/authority.lib.ftl @@ -11,10 +11,10 @@ <#if authority.adminGroup??>"isAdminGroup": ${authority.adminGroup?string("true", "false")}, <#-- end of group specific properties --> <#if authority.authorityType = "GROUP"> - "url": "/api/groups/${authority.shortName}" + "url": "/api/groups/${authority.shortName?url}" <#if authority.authorityType = "USER"> - "url": "/api/people/${authority.shortName}" + "url": "/api/people/${authority.shortName?url}" } diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/evaluator.lib.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/evaluator.lib.js index a59557de53..004ecb2f54 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/evaluator.lib.js +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/evaluator.lib.js @@ -169,7 +169,7 @@ var Evaluator = var wcNode = node.properties["source"]; custom["isWorkingCopy"] = true; custom["workingCopyOriginal"] = wcNode.nodeRef; - if (wcNode.hasAspect("cm:versionable") && wcNode.versionHistory.length > 0) + if (wcNode.hasAspect("cm:versionable") && wcNode.versionHistory !== null && wcNode.versionHistory.length > 0) { custom["workingCopyVersion"] = wcNode.versionHistory[0].label; } diff --git a/source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java b/source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java index 37b99af19a..0483f72a37 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java @@ -22,6 +22,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; +import java.net.URLConnection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -44,6 +46,7 @@ import org.dom4j.XPath; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; +import org.springframework.beans.factory.InitializingBean; import org.springframework.extensions.config.Config; import org.springframework.extensions.config.ConfigService; import org.springframework.extensions.webscripts.AbstractWebScript; @@ -52,7 +55,6 @@ import org.springframework.extensions.webscripts.WebScriptException; import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; -import org.springframework.beans.factory.InitializingBean; /** @@ -166,7 +168,8 @@ public class SearchProxy extends AbstractWebScript implements InitializingBean } HttpServletResponse servletRes = WebScriptServletRuntime.getHttpServletResponse(res); - SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServicePath() + "/" + req.getContextPath(), engine, engineUrl, servletRes); + SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServicePath() + "/" + req.getContextPath(), + engine, engineUrl, servletRes, Collections.singletonMap("User-Agent", req.getHeader("User-Agent"))); proxy.service(); } @@ -184,20 +187,38 @@ public class SearchProxy extends AbstractWebScript implements InitializingBean private final static String ATOM_LINK_XPATH = "atom:link[@rel=\"first\" or @rel=\"last\" or @rel=\"next\" or @rel=\"previous\" or @rel=\"self\" or @rel=\"alternate\"]"; private String engine; private String rootPath; + private Map headers; /** * Construct * * @param requestUrl * @param response + * @param headers request headers * @throws MalformedURLException */ - public SearchEngineHttpProxy(String rootPath, String engine, String engineUrl, HttpServletResponse response) + public SearchEngineHttpProxy(String rootPath, String engine, String engineUrl, HttpServletResponse response, Map headers) throws MalformedURLException { super(engineUrl.startsWith("/") ? rootPath + engineUrl : engineUrl, response); this.engine = engine; this.rootPath = rootPath; + this.headers = headers; + } + + /* (non-Javadoc) + * @see org.alfresco.web.app.servlet.HTTPProxy#setRequestHeaders(java.net.URLConnection) + */ + @Override + protected void setRequestHeaders(URLConnection urlConnection) + { + if (headers != null) + { + for (Map.Entry entry: headers.entrySet()) + { + urlConnection.setRequestProperty(entry.getKey(), entry.getValue()); + } + } } /* (non-Javadoc) diff --git a/source/java/org/alfresco/repo/webdav/LockMethod.java b/source/java/org/alfresco/repo/webdav/LockMethod.java index d5b0840369..6b2be06678 100644 --- a/source/java/org/alfresco/repo/webdav/LockMethod.java +++ b/source/java/org/alfresco/repo/webdav/LockMethod.java @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2005-2010 Alfresco Software Limited. * * This file is part of Alfresco @@ -14,492 +14,427 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -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; - -import org.alfresco.model.ContentModel; -import org.alfresco.model.WebDAVModel; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.lock.LockType; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.model.FileFolderUtil; -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.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 LOCK method - * - * @author gavinc - */ -public class LockMethod extends WebDAVMethod -{ - public static final String EMPTY_NS = ""; - - protected int m_timeoutDuration = WebDAV.TIMEOUT_INFINITY; - - protected LockInfo lockInfo = new LockInfo(); - - protected String m_scope = null; - - protected String lockToken= null; - - /** - * Default constructor - */ - public LockMethod() - { - } - - /** - * Returns true if request has lock token in the If header - * - * @return boolean - */ - protected final boolean hasLockToken() - { - if (m_conditions != null) - { - for (Condition condition : m_conditions) - { - if (!condition.getLockTokensMatch().isEmpty()) - { - return true; - } - } - } - return false; - } - - /** - * Return the lock timeout, in minutes - * - * @return int - */ - protected final int getLockTimeout() - { - return m_timeoutDuration; - } - - /** - * Parse the request headers - * - * @exception WebDAVServerException - */ - protected void parseRequestHeaders() throws WebDAVServerException - { - // Get the depth - - parseDepthHeader(); - - // According to the specification: "Values other than 0 or infinity MUST NOT be used with the Depth header on a LOCK method.". - // The specification does not specify the error code for this case - so we use HttpServletResponse.SC_INTERNAL_SERVER_ERROR. - if (m_depth != WebDAV.DEPTH_0 && m_depth != WebDAV.DEPTH_INFINITY) - { - throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - - // Parse Lock tokens and ETags, if any - - parseIfHeader(); - - // Get the lock timeout value - - String strTimeout = m_request.getHeader(WebDAV.HEADER_TIMEOUT); - - // If the timeout header starts with anything other than Second - // leave the timeout as the default - - if (strTimeout != null && strTimeout.startsWith(WebDAV.SECOND)) - { - try - { - // Some clients send header as Second-180 Seconds so we need to - // look for the space - - int idx = strTimeout.indexOf(" "); - - if (idx != -1) - { - // Get the bit after Second- and before the space - - strTimeout = strTimeout.substring(WebDAV.SECOND.length(), idx); - } - else - { - // The string must be in the correct format - - strTimeout = strTimeout.substring(WebDAV.SECOND.length()); - } - m_timeoutDuration = Integer.parseInt(strTimeout); - } - catch (Exception e) - { - // Warn about the parse failure and leave the timeout as the - // default - - logger.warn("Failed to parse Timeout header: " + strTimeout); - } - } - - // DEBUG - - if (logger.isDebugEnabled()) - logger.debug("Timeout=" + getLockTimeout() + ", depth=" + getDepth()); - } - - /** - * Parse the request body - * - * @exception WebDAVServerException - */ - protected void parseRequestBody() throws WebDAVServerException - { - if (m_request.getContentLength() == -1) - { - return; - } - - Document body = getRequestBodyAsDocument(); - if (body != null) - { - Element rootElement = body.getDocumentElement(); - NodeList childList = rootElement.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: - if (currentNode.getNodeName().endsWith(WebDAV.XML_LOCK_SCOPE)) - { - 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: - m_scope = propertiesNode.getLocalName(); - break; - } - } - } - break; - } - } - } - } - - /** - * Execute the request - * - * @exception WebDAVServerException - */ - protected void executeImpl() throws WebDAVServerException, Exception - { - FileFolderService fileFolderService = getFileFolderService(); - String path = getPath(); - NodeRef rootNodeRef = getRootNodeRef(); - // Get the active user - String userName = getDAVHelper().getAuthenticationService().getCurrentUserName(); - - if (logger.isDebugEnabled()) - { - logger.debug("Locking node: \n" + - " user: " + userName + "\n" + - " path: " + path); - } - - FileInfo lockNodeInfo = null; - try - { - // Check if the path exists - lockNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), getPath(), m_request.getServletPath()); - } - catch (FileNotFoundException e) - { - // need to create it - String[] splitPath = getDAVHelper().splitPath(path); - // check - if (splitPath[1].length() == 0) - { - throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - - FileInfo dirInfo = null; - List dirPathElements = getDAVHelper().splitAllPaths(splitPath[0]); - if (dirPathElements.size() == 0) - { - // if there are no path elements we are at the root so get the root node - dirInfo = fileFolderService.getFileInfo(getRootNodeRef()); - } - else - { - // make sure folder structure is present - dirInfo = FileFolderUtil.makeFolders(fileFolderService, rootNodeRef, dirPathElements, ContentModel.TYPE_FOLDER); - } - - if (dirInfo == null) - { - throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - - // create the file - lockNodeInfo = fileFolderService.create(dirInfo.getNodeRef(), splitPath[1], ContentModel.TYPE_CONTENT); - - if (logger.isDebugEnabled()) - { - logger.debug("Created new node for lock: \n" + - " path: " + path + "\n" + - " node: " + lockNodeInfo); - } - - m_response.setStatus(HttpServletResponse.SC_CREATED); - } - - - - // Check if this is a new lock or a lock refresh - if (hasLockToken()) - { - this.lockInfo = checkNode(lockNodeInfo); - // Refresh an existing lock - refreshLock(lockNodeInfo, userName); - } - else - { - this.lockInfo = checkNode(lockNodeInfo, true, WebDAV.XML_EXCLUSIVE.equals(m_scope)); - // Create a new lock - createLock(lockNodeInfo, 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); - } - - /** - * Create a new lock - * - * @param lockNode NodeRef - * @param userName String - * @exception WebDAVServerException - */ - protected final void createLock(FileInfo lockNode, String userName) throws WebDAVServerException - { - LockService lockService = getLockService(); - - // Create Lock token - lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName); - - if (WebDAV.XML_EXCLUSIVE.equals(m_scope)) - { - // Lock the node - lockService.lock(lockNode.getNodeRef(), LockType.WRITE_LOCK, getLockTimeout()); - - //this.lockInfo.setToken(lockToken); - getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_OPAQUE_LOCK_TOKEN, lockToken); - } - else - { - this.lockInfo.addSharedLockToken(lockToken); - String sharedLockTokens = LockInfo.makeSharedLockTokensString(this.lockInfo.getSharedLockTokens()); - getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_SHARED_LOCK_TOKENS, sharedLockTokens); - - } - - // Store lock depth - getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_LOCK_DEPTH, WebDAV.getDepthName(m_depth)); - - // Store lock scope (shared/exclusive) - getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_LOCK_SCOPE, m_scope); - - } - - /** - * Refresh an existing lock - * - * @param lockNode NodeRef - * @param userName String - * @exception WebDAVServerException - */ - protected final void refreshLock(FileInfo lockNode, String userName) throws WebDAVServerException - { - LockService lockService = getLockService(); - - if (WebDAV.XML_EXCLUSIVE.equals(m_scope)) - { - // Update the expiry for the lock - lockService.lock(lockNode.getNodeRef(), LockType.WRITE_LOCK, getLockTimeout()); - } - } - - /** - * Generates the XML lock discovery response body - */ - protected void generateResponse(NodeRef lockNode, String userName) throws Exception - { - XMLWriter xml = createXMLWriter(); - - xml.startDocument(); - - String nsdec = generateNamespaceDeclarations(null); - 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(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); - - xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_LOCK_SCOPE, nullAttr); - if (lockToken != null) - { - // In case of lock creation take the scope from request header - xml.write(DocumentHelper.createElement(m_scope)); - } - else - { - // In case of lock refreshing take the scope from previously stored lock - xml.write(DocumentHelper.createElement(this.lockInfo.getScope())); - } - xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_LOCK_SCOPE); - - xml.startElement(EMPTY_NS, WebDAV.XML_DEPTH, WebDAV.XML_DEPTH, nullAttr); - xml.write(WebDAV.getDepthName(m_depth)); - 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); - if (lockToken != null) - { - // Output created lock - xml.write(lockToken); - } - else - { - // Output refreshed lock - xml.write(this.lockInfo.getToken()); - } - 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(); - } - - -} + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.webdav; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.model.ContentModel; +import org.alfresco.model.WebDAVModel; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.lock.LockType; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileFolderUtil; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.dom4j.io.XMLWriter; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Implements the WebDAV LOCK method + * + * @author gavinc + */ +public class LockMethod extends WebDAVMethod +{ + public static final String EMPTY_NS = ""; + + private int m_timeoutDuration = WebDAV.TIMEOUT_INFINITY; + + private LockInfo lockInfo = new LockInfo(); + + private boolean createExclusive; + + private String lockToken= null; + + /** + * Default constructor + */ + public LockMethod() + { + } + + /** + * Returns true if request has lock token in the If header + * + * @return boolean + */ + protected final boolean hasLockToken() + { + if (m_conditions != null) + { + for (Condition condition : m_conditions) + { + if (!condition.getLockTokensMatch().isEmpty()) + { + return true; + } + } + } + return false; + } + + /** + * Return the lock timeout, in minutes + * + * @return int + */ + protected final int getLockTimeout() + { + return m_timeoutDuration; + } + + /** + * Parse the request headers + * + * @exception WebDAVServerException + */ + protected void parseRequestHeaders() throws WebDAVServerException + { + // Get user Agent + + m_userAgent = m_request.getHeader(WebDAV.HEADER_USER_AGENT); + + // Get the depth + + parseDepthHeader(); + + // According to the specification: "Values other than 0 or infinity MUST NOT be used with the Depth header on a LOCK method.". + // The specification does not specify the error code for this case - so we use HttpServletResponse.SC_INTERNAL_SERVER_ERROR. + if (m_depth != WebDAV.DEPTH_0 && m_depth != WebDAV.DEPTH_INFINITY) + { + throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + // Parse Lock tokens and ETags, if any + + parseIfHeader(); + + // Get the lock timeout value + + String strTimeout = m_request.getHeader(WebDAV.HEADER_TIMEOUT); + + // If the timeout header starts with anything other than Second + // leave the timeout as the default + + if (strTimeout != null && strTimeout.startsWith(WebDAV.SECOND)) + { + try + { + // Some clients send header as Second-180 Seconds so we need to + // look for the space + + int idx = strTimeout.indexOf(" "); + + if (idx != -1) + { + // Get the bit after Second- and before the space + + strTimeout = strTimeout.substring(WebDAV.SECOND.length(), idx); + } + else + { + // The string must be in the correct format + + strTimeout = strTimeout.substring(WebDAV.SECOND.length()); + } + m_timeoutDuration = Integer.parseInt(strTimeout); + } + catch (Exception e) + { + // Warn about the parse failure and leave the timeout as the + // default + + logger.warn("Failed to parse Timeout header: " + strTimeout); + } + } + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Timeout=" + getLockTimeout() + ", depth=" + getDepth()); + } + + /** + * Parse the request body + * + * @exception WebDAVServerException + */ + protected void parseRequestBody() throws WebDAVServerException + { + if (m_request.getContentLength() == -1) + { + return; + } + + Document body = getRequestBodyAsDocument(); + if (body != null) + { + OUTER: for (Node currentNode = body.getDocumentElement().getFirstChild(); currentNode != null; currentNode = currentNode.getNextSibling()) + { + if (currentNode instanceof Element && WebDAV.DEFAULT_NAMESPACE_URI.equals(((Element) currentNode).getNamespaceURI()) + && WebDAV.XML_LOCK_SCOPE.equals(((Element) currentNode).getLocalName())) + { + for (Node propertiesNode = currentNode.getFirstChild(); propertiesNode != null; propertiesNode = propertiesNode.getNextSibling()) + { + if (propertiesNode instanceof Element && WebDAV.DEFAULT_NAMESPACE_URI.equals(((Element) propertiesNode).getNamespaceURI())) + { + this.createExclusive = WebDAV.XML_EXCLUSIVE.equals(propertiesNode.getLocalName()); + break OUTER; + } + } + break OUTER; + } + } + } + } + + /** + * Execute the request + * + * @exception WebDAVServerException + */ + protected void executeImpl() throws WebDAVServerException, Exception + { + FileFolderService fileFolderService = getFileFolderService(); + String path = getPath(); + NodeRef rootNodeRef = getRootNodeRef(); + // Get the active user + String userName = getDAVHelper().getAuthenticationService().getCurrentUserName(); + + if (logger.isDebugEnabled()) + { + logger.debug("Locking node: \n" + + " user: " + userName + "\n" + + " path: " + path); + } + + FileInfo lockNodeInfo = null; + try + { + // Check if the path exists + lockNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), getPath(), m_request.getServletPath()); + } + catch (FileNotFoundException e) + { + // need to create it + String[] splitPath = getDAVHelper().splitPath(path); + // check + if (splitPath[1].length() == 0) + { + throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + FileInfo dirInfo = null; + List dirPathElements = getDAVHelper().splitAllPaths(splitPath[0]); + if (dirPathElements.size() == 0) + { + // if there are no path elements we are at the root so get the root node + dirInfo = fileFolderService.getFileInfo(getRootNodeRef()); + } + else + { + // make sure folder structure is present + dirInfo = FileFolderUtil.makeFolders(fileFolderService, rootNodeRef, dirPathElements, ContentModel.TYPE_FOLDER); + } + + if (dirInfo == null) + { + throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + // create the file + lockNodeInfo = fileFolderService.create(dirInfo.getNodeRef(), splitPath[1], ContentModel.TYPE_CONTENT); + + if (logger.isDebugEnabled()) + { + logger.debug("Created new node for lock: \n" + + " path: " + path + "\n" + + " node: " + lockNodeInfo); + } + + m_response.setStatus(HttpServletResponse.SC_CREATED); + } + + + + // Check if this is a new lock or a lock refresh + if (hasLockToken()) + { + this.lockInfo = checkNode(lockNodeInfo); + // If a request body is not defined and "If" header is sent we have createExclusive as false, + // but we need to check a previous LOCK was an exclusive. I.e. get the property for node. It + // is already has got in a checkNode method, so we need just get a scope from lockInfo. + // This particular case was raised as ALF-4008. + this.createExclusive = WebDAV.XML_EXCLUSIVE.equals(this.lockInfo.getScope()); + // Refresh an existing lock + refreshLock(lockNodeInfo, userName); + } + else + { + this.lockInfo = checkNode(lockNodeInfo, true, this.createExclusive); + // Create a new lock + createLock(lockNodeInfo, 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); + } + + /** + * Create a new lock + * + * @param lockNode NodeRef + * @param userName String + * @exception WebDAVServerException + */ + protected final void createLock(FileInfo lockNode, String userName) throws WebDAVServerException + { + LockService lockService = getLockService(); + + // Create Lock token + lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName); + + if (this.createExclusive) + { + // Lock the node + lockService.lock(lockNode.getNodeRef(), LockType.WRITE_LOCK, getLockTimeout()); + + //this.lockInfo.setToken(lockToken); + getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_OPAQUE_LOCK_TOKEN, lockToken); + } + else + { + this.lockInfo.addSharedLockToken(lockToken); + String sharedLockTokens = LockInfo.makeSharedLockTokensString(this.lockInfo.getSharedLockTokens()); + getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_SHARED_LOCK_TOKENS, sharedLockTokens); + + } + + // Store lock depth + getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_LOCK_DEPTH, WebDAV.getDepthName(m_depth)); + + // Store lock scope (shared/exclusive) + getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_LOCK_SCOPE, this.createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED); + + } + + /** + * Refresh an existing lock + * + * @param lockNode NodeRef + * @param userName String + * @exception WebDAVServerException + */ + private final void refreshLock(FileInfo lockNode, String userName) throws WebDAVServerException + { + if (this.createExclusive) + { + // Update the expiry for the lock + getLockService().lock(lockNode.getNodeRef(), LockType.WRITE_LOCK, getLockTimeout()); + } + } + + /** + * Generates the XML lock discovery response body + */ + private void generateResponse(NodeRef lockNode, String userName) throws Exception + { + String scope; + String lt; + if (lockToken != null) + { + // In case of lock creation take the scope from request header + scope = this.createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED; + // Output created lock + lt = lockToken; + } + else + { + // In case of lock refreshing take the scope from previously stored lock + scope = this.lockInfo.getScope(); + // Output refreshed lock + lt = this.lockInfo.getToken(); + } + String owner = (String) getNodeService().getProperty(lockNode, ContentModel.PROP_LOCK_OWNER); + + XMLWriter xml = createXMLWriter(); + + xml.startDocument(); + + // Output the lock details + String nsdec = generateNamespaceDeclarations(null); + + if (WebDAV.AGENT_MS_6_1_7600.equals(m_userAgent)) + { + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP + nsdec, WebDAV.XML_NS_PROP + nsdec, getDAVHelper().getNullAttributes()); + + // Output the lock details + generateLockDiscoveryXML(xml, lockNode, false, scope, WebDAV.getDepthName(m_depth), lt, owner); + + // Close off the XML + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP); + + } + else + { + xml.startElement(EMPTY_NS, WebDAV.XML_PROP + nsdec, WebDAV.XML_PROP + nsdec, getDAVHelper().getNullAttributes()); + + // Output the lock details + generateLockDiscoveryXML(xml, lockNode, true, scope, WebDAV.getDepthName(m_depth), lt, owner); + + // Close off the XML + xml.endElement(EMPTY_NS, WebDAV.XML_PROP, WebDAV.XML_PROP); + } + + // Send the XML back to the client + xml.flush(); + } + + + /** + * 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 d4d3187cfa..520c736589 100644 --- a/source/java/org/alfresco/repo/webdav/PropFindMethod.java +++ b/source/java/org/alfresco/repo/webdav/PropFindMethod.java @@ -18,6 +18,7 @@ */ package org.alfresco.repo.webdav; +import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; @@ -46,6 +47,7 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.Attributes; +import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; /** @@ -908,13 +910,10 @@ public class PropFindMethod extends WebDAVMethod xml.startElement(WebDAV.DAV_NS, WebDAV.XML_SUPPORTED_LOCK, WebDAV.XML_NS_SUPPORTED_LOCK, nullAttr); - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr); - xml.write(DocumentHelper.createElement(WebDAV.XML_NS_EXCLUSIVE)); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE); - - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE, nullAttr); - xml.write(DocumentHelper.createElement(WebDAV.XML_NS_WRITE)); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE); + // Output exclusive lock + writeLock(xml, WebDAV.XML_NS_EXCLUSIVE); + // Output shared lock + writeLock(xml, WebDAV.XML_NS_SHARED); xml.endElement(WebDAV.DAV_NS, WebDAV.XML_SUPPORTED_LOCK, WebDAV.XML_NS_SUPPORTED_LOCK); } @@ -923,4 +922,27 @@ public class PropFindMethod extends WebDAVMethod throw new AlfrescoRuntimeException("XML write error", ex); } } + + /** + * Output the lockentry element of the specified type + * @param xml XMLWriter + * @param lockType lock type. Can be WebDAV.XML_NS_EXCLUSIVE or WebDAV.XML_NS_SHARED + * @param lockType lock type containing namespace + * @throws SAXException + * @throws IOException + */ + private void writeLock(XMLWriter xml, String lockType) throws SAXException, IOException + { + AttributesImpl nullAttr = getDAVHelper().getNullAttributes(); + + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_ENTRY, WebDAV.XML_NS_LOCK_ENTRY, nullAttr); + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr); + xml.write(DocumentHelper.createElement(lockType)); + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE); + + xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE, nullAttr); + xml.write(DocumentHelper.createElement(WebDAV.XML_NS_WRITE)); + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE); + xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_ENTRY, WebDAV.XML_NS_LOCK_ENTRY); + } } diff --git a/source/java/org/alfresco/repo/webdav/PropPatchMethod.java b/source/java/org/alfresco/repo/webdav/PropPatchMethod.java index 176be00c22..ac62ab176a 100644 --- a/source/java/org/alfresco/repo/webdav/PropPatchMethod.java +++ b/source/java/org/alfresco/repo/webdav/PropPatchMethod.java @@ -172,7 +172,8 @@ public class PropPatchMethod extends PropFindMethod @Override protected void parseRequestHeaders() throws WebDAVServerException { - // Nothing to do in this method + // Parse Lock tokens and ETags, if any + parseIfHeader(); } /** diff --git a/source/java/org/alfresco/repo/webdav/UnlockMethod.java b/source/java/org/alfresco/repo/webdav/UnlockMethod.java index 0ec5363e09..43884d63f2 100644 --- a/source/java/org/alfresco/repo/webdav/UnlockMethod.java +++ b/source/java/org/alfresco/repo/webdav/UnlockMethod.java @@ -22,6 +22,7 @@ import java.util.LinkedList; import javax.servlet.http.HttpServletResponse; +import org.alfresco.model.ContentModel; import org.alfresco.model.WebDAVModel; import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.LockStatus; @@ -140,8 +141,11 @@ public class UnlockMethod extends WebDAVMethod LockStatus lockSts = lockService.getLockStatus(lockNodeInfo.getNodeRef()); if (lockSts == LockStatus.LOCK_OWNER) { - // Unlock the node - lockService.unlock(lockNodeInfo.getNodeRef()); + // Unlock the node if it is not a Working Copy (ALF-4479) + if (!nodeService.hasAspect(lockNodeInfo.getNodeRef(), ContentModel.ASPECT_WORKING_COPY)) + { + lockService.unlock(lockNodeInfo.getNodeRef()); + } nodeService.removeProperty(lockNodeInfo.getNodeRef(), WebDAVModel.PROP_OPAQUE_LOCK_TOKEN); nodeService.removeProperty(lockNodeInfo.getNodeRef(), WebDAVModel.PROP_LOCK_DEPTH); nodeService.removeProperty(lockNodeInfo.getNodeRef(), WebDAVModel.PROP_LOCK_SCOPE); diff --git a/source/java/org/alfresco/repo/webdav/WebDAV.java b/source/java/org/alfresco/repo/webdav/WebDAV.java index 9134e4faea..df49f8e50f 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAV.java +++ b/source/java/org/alfresco/repo/webdav/WebDAV.java @@ -114,6 +114,7 @@ public class WebDAV public static final String HEADER_OVERWRITE = "Overwrite"; public static final String HEADER_RANGE = "Range"; public static final String HEADER_TIMEOUT = "Timeout"; + public static final String HEADER_USER_AGENT = "User-Agent"; // If-Modified/If-Unmodified date format @@ -123,6 +124,10 @@ public class WebDAV public static final String HEADER_KEY_NOT = "Not"; + // User agents + + public static final String AGENT_MS_6_1_7600 = "Microsoft-WebDAV-MiniRedir/6.1.7600"; + // General string constants public static final String ASTERISK = "*"; @@ -158,6 +163,7 @@ public class WebDAV public static final String XML_GET_LAST_MODIFIED = "getlastmodified"; public static final String XML_HREF = "href"; public static final String XML_LOCK_DISCOVERY = "lockdiscovery"; + public static final String XML_LOCK_ENTRY = "lockentry"; public static final String XML_LOCK_SCOPE = "lockscope"; public static final String XML_LOCK_TOKEN = "locktoken"; public static final String XML_LOCK_TYPE = "locktype"; @@ -194,6 +200,7 @@ public class WebDAV public static final String XML_NS_GET_LAST_MODIFIED = DAV_NS_PREFIX + "getlastmodified"; public static final String XML_NS_HREF = DAV_NS_PREFIX + "href"; public static final String XML_NS_LOCK_DISCOVERY = DAV_NS_PREFIX + "lockdiscovery"; + public static final String XML_NS_LOCK_ENTRY = DAV_NS_PREFIX + "lockentry"; public static final String XML_NS_LOCK_SCOPE = DAV_NS_PREFIX + "lockscope"; public static final String XML_NS_LOCK_TOKEN = DAV_NS_PREFIX + "locktoken"; public static final String XML_NS_LOCK_TYPE = DAV_NS_PREFIX + "locktype"; diff --git a/source/java/org/alfresco/repo/webdav/WebDAVMethod.java b/source/java/org/alfresco/repo/webdav/WebDAVMethod.java index fd0b65a23c..a6d7c54690 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAVMethod.java +++ b/source/java/org/alfresco/repo/webdav/WebDAVMethod.java @@ -106,6 +106,9 @@ public abstract class WebDAVMethod protected String m_strPath = null; + // User Agent + + protected String m_userAgent = null; // If header conditions @@ -691,16 +694,34 @@ public abstract class WebDAVMethod return writer; } - /** + /** * Generates the lock discovery XML response * * @param xml XMLWriter * @param lockNode NodeRef */ protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode, LockInfo lockInfo) throws Exception + { + String owner = (String) getNodeService().getProperty(lockNode, ContentModel.PROP_LOCK_OWNER); + generateLockDiscoveryXML(xml, lockNode, false, lockInfo.getScope(), lockInfo.getDepth(), WebDAV.makeLockToken(lockNode, owner), owner); + } + + /** + * Generates the lock discovery XML response + * + * @param xml XMLWriter + * @param lockNode NodeRef + * @param emptyNamespace boolean True if namespace should be empty. Used to avoid bugs in WebDAV clients. + * @param scope String lock scope + * @param depth String lock depth + * @param lToken String locktoken + * @param owner String lock owner + * + */ + protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode, boolean emptyNamespace, String scope, String depth, String lToken, String owner) throws Exception { Attributes nullAttr= getDAVHelper().getNullAttributes(); - + String ns = emptyNamespace ? "" : WebDAV.DAV_NS; if (lockNode != null) { @@ -708,35 +729,32 @@ public abstract class WebDAVMethod 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(WebDAV.DAV_NS, WebDAV.XML_LOCK_DISCOVERY, WebDAV.XML_NS_LOCK_DISCOVERY, nullAttr); - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_ACTIVE_LOCK, WebDAV.XML_NS_ACTIVE_LOCK, nullAttr); + xml.startElement(ns, WebDAV.XML_LOCK_DISCOVERY, emptyNamespace ? WebDAV.XML_LOCK_DISCOVERY : WebDAV.XML_NS_LOCK_DISCOVERY, nullAttr); + xml.startElement(ns, WebDAV.XML_ACTIVE_LOCK, emptyNamespace ? WebDAV.XML_ACTIVE_LOCK : WebDAV.XML_NS_ACTIVE_LOCK, nullAttr); - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE, nullAttr); - xml.write(DocumentHelper.createElement(WebDAV.XML_NS_WRITE)); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE); + xml.startElement(ns, WebDAV.XML_LOCK_TYPE, emptyNamespace ? WebDAV.XML_LOCK_TYPE : WebDAV.XML_NS_LOCK_TYPE, nullAttr); + xml.write(DocumentHelper.createElement(emptyNamespace ? WebDAV.XML_WRITE : WebDAV.XML_NS_WRITE)); + xml.endElement(ns, WebDAV.XML_LOCK_TYPE, emptyNamespace ? WebDAV.XML_LOCK_TYPE : WebDAV.XML_NS_LOCK_TYPE); - // NOTE: We only do exclusive lock tokens at the moment - - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr); - xml.write(DocumentHelper.createElement(lockInfo.getScope())); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE); + xml.startElement(ns, WebDAV.XML_LOCK_SCOPE, emptyNamespace ? WebDAV.XML_LOCK_SCOPE : WebDAV.XML_NS_LOCK_SCOPE, nullAttr); + xml.write(DocumentHelper.createElement(scope)); + xml.endElement(ns, WebDAV.XML_LOCK_SCOPE, emptyNamespace ? WebDAV.XML_LOCK_SCOPE : WebDAV.XML_NS_LOCK_SCOPE); // NOTE: We only support one level of lock at the moment - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH, nullAttr); - xml.write(lockInfo.getDepth()); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH); + xml.startElement(ns, WebDAV.XML_DEPTH, emptyNamespace ? WebDAV.XML_DEPTH : WebDAV.XML_NS_DEPTH, nullAttr); + xml.write(depth); + xml.endElement(ns, WebDAV.XML_DEPTH, emptyNamespace ? WebDAV.XML_DEPTH : WebDAV.XML_NS_DEPTH); - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_OWNER, WebDAV.XML_NS_OWNER, nullAttr); + xml.startElement(ns, WebDAV.XML_OWNER, emptyNamespace ? WebDAV.XML_OWNER : WebDAV.XML_NS_OWNER, nullAttr); xml.write(owner); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_OWNER, WebDAV.XML_NS_OWNER); + xml.endElement(ns, WebDAV.XML_OWNER, emptyNamespace ? WebDAV.XML_OWNER : WebDAV.XML_NS_OWNER); - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_TIMEOUT, WebDAV.XML_NS_TIMEOUT, nullAttr); + xml.startElement(ns, WebDAV.XML_TIMEOUT, emptyNamespace ? WebDAV.XML_TIMEOUT : WebDAV.XML_NS_TIMEOUT, nullAttr); // Output the expiry time @@ -749,18 +767,18 @@ public abstract class WebDAVMethod } xml.write(strTimeout); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_TIMEOUT, WebDAV.XML_NS_TIMEOUT); + xml.endElement(ns, WebDAV.XML_TIMEOUT, emptyNamespace ? WebDAV.XML_TIMEOUT : WebDAV.XML_NS_TIMEOUT); - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_NS_LOCK_TOKEN, nullAttr); - xml.startElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF, nullAttr); + xml.startElement(ns, WebDAV.XML_LOCK_TOKEN, emptyNamespace ? WebDAV.XML_LOCK_TOKEN : WebDAV.XML_NS_LOCK_TOKEN, nullAttr); + xml.startElement(ns, WebDAV.XML_HREF, emptyNamespace ? WebDAV.XML_HREF : WebDAV.XML_NS_HREF, nullAttr); - xml.write(WebDAV.makeLockToken(lockNode, owner)); + xml.write(lToken); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_NS_LOCK_TOKEN); + xml.endElement(ns, WebDAV.XML_HREF, emptyNamespace ? WebDAV.XML_HREF : WebDAV.XML_NS_HREF); + xml.endElement(ns, WebDAV.XML_LOCK_TOKEN, emptyNamespace ? WebDAV.XML_LOCK_TOKEN : WebDAV.XML_NS_LOCK_TOKEN); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_ACTIVE_LOCK, WebDAV.XML_NS_ACTIVE_LOCK); - xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_DISCOVERY, WebDAV.XML_NS_LOCK_DISCOVERY); + xml.endElement(ns, WebDAV.XML_ACTIVE_LOCK, emptyNamespace ? WebDAV.XML_ACTIVE_LOCK : WebDAV.XML_NS_ACTIVE_LOCK); + xml.endElement(ns, WebDAV.XML_LOCK_DISCOVERY, emptyNamespace ? WebDAV.XML_LOCK_DISCOVERY : WebDAV.XML_NS_LOCK_DISCOVERY); } } diff --git a/source/java/org/alfresco/web/app/servlet/HTTPProxy.java b/source/java/org/alfresco/web/app/servlet/HTTPProxy.java index 89ffa6f6d7..65b08f3622 100644 --- a/source/java/org/alfresco/web/app/servlet/HTTPProxy.java +++ b/source/java/org/alfresco/web/app/servlet/HTTPProxy.java @@ -63,6 +63,7 @@ public class HTTPProxy throws IOException { HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + setRequestHeaders(connection); initialiseResponse(connection); InputStream input = connection.getInputStream(); OutputStream output = response.getOutputStream(); @@ -117,6 +118,15 @@ public class HTTPProxy } } + /** + * Set request headers + * + * @param urlConnection url connection + */ + protected void setRequestHeaders(URLConnection urlConnection) + { + } + /** * Write response *