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();
}
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();
}
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());
}
}
Aggregations