org.cryptomator.frontend.webdav.DefaultServlet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webdav-nio-adapter Show documentation
Show all versions of webdav-nio-adapter Show documentation
Embedded Jetty serving a WebDAV servlet to access resources at a given NIO path.
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE.txt.
*
* Contributors:
* Sebastian Stenzel - initial API and implementation
*******************************************************************************/
package org.cryptomator.frontend.webdav;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.regex.Pattern;
class DefaultServlet extends HttpServlet {
private static final String METHOD_PROPFIND = "PROPFIND";
private static final int TARPIT_DELAY_MS = 5000;
private static final Pattern PATH_SEP_PATTERN = Pattern.compile("/");
private final Collection contextPaths;
public DefaultServlet(Collection contextPaths) {
this.contextPaths = contextPaths;
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (!isRequestedResourcePathPartOfValidContextPath(req.getRequestURI())) {
try {
Thread.sleep(TARPIT_DELAY_MS);
resp.addHeader("X-Tarpit-Delayed", TARPIT_DELAY_MS + "ms");
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
} catch (InterruptedException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Thread interrupted.");
Thread.currentThread().interrupt();
}
return;
}
switch (req.getMethod()) {
case METHOD_PROPFIND:
doPropfind(req, resp);
break;
default:
super.service(req, resp);
break;
}
}
@Override
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) {
resp.addHeader("DAV", "1, 2");
resp.addHeader("MS-Author-Via", "DAV");
resp.addHeader("Allow", "OPTIONS, PROPFIND, GET, HEAD");
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
protected void doPropfind(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.getWriter()
.write("\n" //
+ "\n" //
+ "\n" //
+ " " + req.getRequestURI() + " \n" //
+ " \n" //
+ " \n" //
+ " 1 \n" //
+ " \n" //
+ " \n" //
+ " \n" //
+ " \n" //
+ " ");
resp.getWriter().flush();
}
private boolean isRequestedResourcePathPartOfValidContextPath(String requestedResourcePath) {
return contextPaths.stream().anyMatch(cp -> isParentOrSamePath(cp, requestedResourcePath));
}
private boolean isParentOrSamePath(String path, String potentialParent) {
String[] pathComponents = PATH_SEP_PATTERN.splitAsStream(path).filter(Predicate.not(String::isBlank)).toArray(String[]::new);
String[] parentPathComponents = PATH_SEP_PATTERN.splitAsStream(potentialParent).filter(Predicate.not(String::isBlank)).toArray(String[]::new);
if (pathComponents.length < parentPathComponents.length) {
return false; // parent can not be parent of path, if it is longer than path.
}
assert pathComponents.length >= parentPathComponents.length;
for (int i = 0; i < parentPathComponents.length; i++) {
if (!pathComponents[i].equals(parentPathComponents[i])) {
return false;
}
}
return true;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy