mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-08-17 04:36:02 +00:00
- fixed #19 (again): vault-specific prefix is now handled by the servlet context instead of jackrabbit.
- simplified webdav locator, as workspaces and pathPrefixes are not relevant to jackrabbit any longer
This commit is contained in:
@@ -20,6 +20,7 @@ import org.cryptomator.webdav.jackrabbit.WebDavServlet;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
@@ -39,7 +40,7 @@ public final class WebDavServer {
|
||||
private static final WebDavServer INSTANCE = new WebDavServer();
|
||||
private final Server server;
|
||||
private final ServerConnector localConnector;
|
||||
private final ServletContextHandler servletContext;
|
||||
private final ContextHandlerCollection servletCollection;
|
||||
|
||||
public static WebDavServer getInstance() {
|
||||
return INSTANCE;
|
||||
@@ -51,10 +52,9 @@ public final class WebDavServer {
|
||||
server = new Server(tp);
|
||||
localConnector = new ServerConnector(server);
|
||||
localConnector.setHost(LOCALHOST);
|
||||
servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
servletContext.setContextPath("/");
|
||||
servletCollection = new ContextHandlerCollection();
|
||||
server.setConnectors(new Connector[] {localConnector});
|
||||
server.setHandler(servletContext);
|
||||
server.setHandler(servletCollection);
|
||||
}
|
||||
|
||||
public synchronized void start() {
|
||||
@@ -87,22 +87,22 @@ public final class WebDavServer {
|
||||
try {
|
||||
final URI uri = new URI(null, null, localConnector.getHost(), localConnector.getLocalPort(), "/" + UUID.randomUUID().toString(), null, null);
|
||||
|
||||
final String pathPrefix = uri.getRawPath() + "/";
|
||||
final String pathSpec = pathPrefix + "*";
|
||||
final ServletHolder servlet = getWebDavServletHolder(workDir.toString(), pathPrefix, checkFileIntegrity, cryptor);
|
||||
servletContext.addServlet(servlet, pathSpec);
|
||||
final ServletContextHandler servletContext = new ServletContextHandler(servletCollection, uri.getRawPath(), ServletContextHandler.SESSIONS);
|
||||
final ServletHolder servlet = getWebDavServletHolder(workDir.toString(), checkFileIntegrity, cryptor);
|
||||
servletContext.addServlet(servlet, "/*");
|
||||
|
||||
LOG.info("{} available on http:{}", workDir, uri.getRawSchemeSpecificPart());
|
||||
return new ServletLifeCycleAdapter(servlet, uri);
|
||||
servletCollection.mapContexts();
|
||||
|
||||
LOG.debug("{} available on http:{}", workDir, uri.getRawSchemeSpecificPart());
|
||||
return new ServletLifeCycleAdapter(servletContext, uri);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalStateException("Invalid hard-coded URI components.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private ServletHolder getWebDavServletHolder(final String workDir, final String contextPath, final boolean checkFileIntegrity, final Cryptor cryptor) {
|
||||
private ServletHolder getWebDavServletHolder(final String workDir, final boolean checkFileIntegrity, final Cryptor cryptor) {
|
||||
final ServletHolder result = new ServletHolder("Cryptomator-WebDAV-Servlet", new WebDavServlet(cryptor));
|
||||
result.setInitParameter(WebDavServlet.CFG_FS_ROOT, workDir);
|
||||
result.setInitParameter(WebDavServlet.CFG_HTTP_ROOT, contextPath);
|
||||
result.setInitParameter(WebDavServlet.CFG_CHECK_FILE_INTEGRITY, Boolean.toString(checkFileIntegrity));
|
||||
return result;
|
||||
}
|
||||
|
||||
+135
-26
@@ -15,31 +15,59 @@ import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
import org.apache.commons.collections4.BidiMap;
|
||||
import org.apache.jackrabbit.webdav.AbstractLocatorFactory;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.jackrabbit.webdav.DavLocatorFactory;
|
||||
import org.apache.jackrabbit.webdav.DavResourceLocator;
|
||||
import org.apache.jackrabbit.webdav.util.EncodeUtil;
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.crypto.CryptorIOSupport;
|
||||
import org.cryptomator.crypto.SensitiveDataSwipeListener;
|
||||
|
||||
class DavLocatorFactoryImpl extends AbstractLocatorFactory implements SensitiveDataSwipeListener, CryptorIOSupport {
|
||||
class DavLocatorFactoryImpl implements DavLocatorFactory, SensitiveDataSwipeListener, CryptorIOSupport {
|
||||
|
||||
private static final int MAX_CACHED_PATHS = 10000;
|
||||
private final Path fsRoot;
|
||||
private final Cryptor cryptor;
|
||||
private final BidiMap<String, String> pathCache = new BidiLRUMap<>(MAX_CACHED_PATHS); // <decryptedPath, encryptedPath>
|
||||
|
||||
DavLocatorFactoryImpl(String fsRoot, String httpRoot, Cryptor cryptor) {
|
||||
super(httpRoot);
|
||||
DavLocatorFactoryImpl(String fsRoot, Cryptor cryptor) {
|
||||
this.fsRoot = FileSystems.getDefault().getPath(fsRoot);
|
||||
this.cryptor = cryptor;
|
||||
cryptor.addSensitiveDataSwipeListener(this);
|
||||
}
|
||||
|
||||
/* DavLocatorFactory */
|
||||
|
||||
@Override
|
||||
public DavResourceLocator createResourceLocator(String prefix, String href) {
|
||||
final String fullPrefix = prefix.endsWith("/") ? prefix : prefix + "/";
|
||||
final String relativeHref = StringUtils.removeStart(href, fullPrefix);
|
||||
|
||||
final String resourcePath = EncodeUtil.unescape(StringUtils.removeStart(relativeHref, "/"));
|
||||
return new DavResourceLocatorImpl(fullPrefix, resourcePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) {
|
||||
final String fullPrefix = prefix.endsWith("/") ? prefix : prefix + "/";
|
||||
|
||||
final String resourcePath = (isResourcePath) ? path : getResourcePath(path);
|
||||
return new DavResourceLocatorImpl(fullPrefix, resourcePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) {
|
||||
return createResourceLocator(prefix, workspacePath, resourcePath, true);
|
||||
}
|
||||
|
||||
/* Encryption/Decryption */
|
||||
|
||||
/**
|
||||
* @return Encrypted absolute paths on the file system.
|
||||
*/
|
||||
@Override
|
||||
protected String getRepositoryPath(String resourcePath, String wspPath) {
|
||||
private String getRepositoryPath(String resourcePath) {
|
||||
String encryptedPath = pathCache.get(resourcePath);
|
||||
if (encryptedPath == null) {
|
||||
encryptedPath = encryptRepositoryPath(resourcePath);
|
||||
@@ -59,8 +87,7 @@ class DavLocatorFactoryImpl extends AbstractLocatorFactory implements SensitiveD
|
||||
/**
|
||||
* @return Decrypted path for use in URIs.
|
||||
*/
|
||||
@Override
|
||||
protected String getResourcePath(String repositoryPath, String wspPath) {
|
||||
private String getResourcePath(String repositoryPath) {
|
||||
String decryptedPath = pathCache.getKey(repositoryPath);
|
||||
if (decryptedPath == null) {
|
||||
decryptedPath = decryptResourcePath(repositoryPath);
|
||||
@@ -80,24 +107,7 @@ class DavLocatorFactoryImpl extends AbstractLocatorFactory implements SensitiveD
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) {
|
||||
// we don't support workspaces
|
||||
return super.createResourceLocator(prefix, "", path, isResourcePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) {
|
||||
// we don't support workspaces
|
||||
return super.createResourceLocator(prefix, "", resourcePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeSensitiveData() {
|
||||
pathCache.clear();
|
||||
}
|
||||
|
||||
/* Cryptor I/O Support */
|
||||
/* CryptorIOSupport */
|
||||
|
||||
@Override
|
||||
public void writePathSpecificMetadata(String encryptedPath, byte[] encryptedMetadata) throws IOException {
|
||||
@@ -115,4 +125,103 @@ class DavLocatorFactoryImpl extends AbstractLocatorFactory implements SensitiveD
|
||||
}
|
||||
}
|
||||
|
||||
/* SensitiveDataSwipeListener */
|
||||
|
||||
@Override
|
||||
public void swipeSensitiveData() {
|
||||
pathCache.clear();
|
||||
}
|
||||
|
||||
/* Locator */
|
||||
|
||||
private class DavResourceLocatorImpl implements DavResourceLocator {
|
||||
|
||||
private final String prefix;
|
||||
private final String resourcePath;
|
||||
|
||||
private DavResourceLocatorImpl(String prefix, String resourcePath) {
|
||||
this.prefix = prefix;
|
||||
this.resourcePath = resourcePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourcePath() {
|
||||
return resourcePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorkspacePath() {
|
||||
return isRootLocation() ? null : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorkspaceName() {
|
||||
return getPrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameWorkspace(DavResourceLocator locator) {
|
||||
return (locator == null) ? false : isSameWorkspace(locator.getWorkspaceName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameWorkspace(String workspaceName) {
|
||||
return getWorkspaceName().equals(workspaceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHref(boolean isCollection) {
|
||||
final String href = getPrefix().concat(getResourcePath());
|
||||
if (isCollection && !href.endsWith("/")) {
|
||||
return href.concat("/");
|
||||
} else if (!isCollection && href.endsWith("/")) {
|
||||
return href.substring(0, href.length() - 1);
|
||||
} else {
|
||||
return href;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRootLocation() {
|
||||
return getResourcePath() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DavLocatorFactory getFactory() {
|
||||
return DavLocatorFactoryImpl.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepositoryPath() {
|
||||
return DavLocatorFactoryImpl.this.getRepositoryPath(getResourcePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final HashCodeBuilder builder = new HashCodeBuilder();
|
||||
builder.append(prefix);
|
||||
builder.append(resourcePath);
|
||||
return builder.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof DavResourceLocatorImpl) {
|
||||
final DavResourceLocatorImpl other = (DavResourceLocatorImpl) obj;
|
||||
final EqualsBuilder builder = new EqualsBuilder();
|
||||
builder.append(this.prefix, other.prefix);
|
||||
builder.append(this.resourcePath, other.resourcePath);
|
||||
return builder.isEquals();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ public class WebDavServlet extends AbstractWebdavServlet {
|
||||
|
||||
private static final long serialVersionUID = 7965170007048673022L;
|
||||
public static final String CFG_FS_ROOT = "cfg.fs.root";
|
||||
public static final String CFG_HTTP_ROOT = "cfg.http.root";
|
||||
public static final String CFG_CHECK_FILE_INTEGRITY = "cfg.checkFileIntegrity";
|
||||
private DavSessionProvider davSessionProvider;
|
||||
private DavLocatorFactory davLocatorFactory;
|
||||
@@ -42,9 +41,8 @@ public class WebDavServlet extends AbstractWebdavServlet {
|
||||
davSessionProvider = new DavSessionProviderImpl();
|
||||
|
||||
final String fsRoot = config.getInitParameter(CFG_FS_ROOT);
|
||||
final String httpRoot = config.getInitParameter(CFG_HTTP_ROOT);
|
||||
final boolean checkFileIntegrity = Boolean.parseBoolean(config.getInitParameter(CFG_CHECK_FILE_INTEGRITY));
|
||||
this.davLocatorFactory = new DavLocatorFactoryImpl(fsRoot, httpRoot, cryptor);
|
||||
this.davLocatorFactory = new DavLocatorFactoryImpl(fsRoot, cryptor);
|
||||
|
||||
this.davResourceFactory = new DavResourceFactoryImpl(cryptor, checkFileIntegrity);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user