* Servlet which adds support for WebDAV level 2. All the basic HTTP requests
* are handled by the DefaultServlet. The WebDAVServlet must not be used as the
* default servlet (ie mapped to '/') as it will not work in this configuration.
- * To enable WebDAV for a context add the following to web.xml:<br/><code>
- * <servlet><br/>
- * <servlet-name>webdav</servlet-name><br/>
- * <servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class><br/>
- * <init-param><br/>
- * <param-name>debug</param-name><br/>
- * <param-value>0</param-value><br/>
- * </init-param><br/>
- * <init-param><br/>
- * <param-name>listings</param-name><br/>
- * <param-value>true</param-value><br/>
- * </init-param><br/>
- * </servlet><br/>
- * <servlet-mapping><br/>
- * <servlet-name>webdav</servlet-name><br/>
- * <url-pattern>/*</url-pattern><br/>
- * </servlet-mapping>
- * </code>
* <p/>
- * This will enable read only access. To enable read-write access add:<br/>
- * <code>
- * <init-param><br/>
- * <param-name>readonly</param-name><br/>
- * <param-value>false</param-value><br/>
- * </init-param><br/>
- * </code>
+ * Mapping a subpath (e.g. <code>/webdav/*</code> to this servlet has the effect
+ * of re-mounting the entire web application under that sub-path, with WebDAV
+ * access to all the resources. This <code>WEB-INF</code> and <code>META-INF</code>
+ * directories are protected in this re-mounted resource tree.
* <p/>
- * To make the content editable via a different URL, using the following
- * mapping:<br/>
- * <code>
- * <servlet-mapping><br/>
- * <servlet-name>webdav</servlet-name><br/>
- * <url-pattern>/webdavedit/*</url-pattern><br/>
+ * To enable WebDAV for a context add the following to web.xml:
+ * <pre>
+ * <servlet>
+ * <servlet-name>webdav</servlet-name>
+ * <servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class>
+ * <init-param>
+ * <param-name>debug</param-name>
+ * <param-value>0</param-value>
+ * </init-param>
+ * <init-param>
+ * <param-name>listings</param-name>
+ * <param-value>false</param-value>
+ * </init-param>
+ * </servlet>
+ * <servlet-mapping>
+ * <servlet-name>webdav</servlet-name>
+ * <url-pattern>/*</url-pattern>
* </servlet-mapping>
- * </code>
- * <p/>
+ * </pre>
+ * This will enable read only access. To enable read-write access add:
+ * <pre>
+ * <init-param>
+ * <param-name>readonly</param-name>
+ * <param-value>false</param-value>
+ * </init-param>
+ * </pre>
+ * To make the content editable via a different URL, use the following
+ * mapping:
+ * <pre>
+ * <servlet-mapping>
+ * <servlet-name>webdav</servlet-name>
+ * <url-pattern>/webdavedit/*</url-pattern>
+ * </servlet-mapping>
+ * </pre>
* Don't forget to secure access appropriately to the editing URLs. With this
* configuration the context will be accessible to normal users as before. Those
* users with the necessary access will be able to edit content available via
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
- String method = req.getMethod();
+ final String path = getRelativePath(req);
+
+ // Block access to special subdirectories.
+ // DefaultServlet assumes it services resources from the root of the web app
+ // and doesn't add any special path protection
+ // WebdavServlet remounts the webapp under a new path, so this check is
+ // necessary on all methods (including GET).
+ if (isSpecialPath(path)) {
+ resp.sendError(WebdavStatus.SC_NOT_FOUND);
+ return;
+ }
+
+ final String method = req.getMethod();
if (debug > 0) {
- String path = getRelativePath(req);
log("[" + method + "] " + path);
}
/**
+ * Checks whether a given path refers to a resource under
+ * <code>WEB-INF</code> or <code>META-INF</code>.
+ * @param path the full path of the resource being accessed
+ * @return <code>true</code> if the resource specified is under a special path
+ */
+ private static final boolean isSpecialPath(final String path) {
+ // FIXME: why isn't this just equalsIgnoreCase?
+ return path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")
+ || path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF");
+ }
+
+
+ /**
* Check if the conditions specified in the optional If headers are
* satisfied.
*
if (path.endsWith("/"))
path = path.substring(0, path.length() - 1);
- if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) ||
- (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) {
- resp.sendError(WebdavStatus.SC_FORBIDDEN);
- return;
- }
-
// Properties which are to be displayed.
Vector<String> properties = null;
// Propfind depth
String path = getRelativePath(req);
- if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) ||
- (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) {
- resp.sendError(WebdavStatus.SC_FORBIDDEN);
- return;
- }
-
boolean exists = true;
try {
resources.lookup(path);
if (debug > 0)
log("Dest path :" + destinationPath);
- if ((destinationPath.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) ||
- (destinationPath.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) {
+ // Check destination path to protect special subdirectories
+ if (isSpecialPath(destinationPath)) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
}
String path = getRelativePath(req);
- if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) ||
- (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) {
- resp.sendError(WebdavStatus.SC_FORBIDDEN);
- return false;
- }
-
if (destinationPath.equals(path)) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
HttpServletResponse resp, boolean setStatus)
throws IOException {
- if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) ||
- (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) {
- resp.sendError(WebdavStatus.SC_FORBIDDEN);
- return false;
- }
-
String ifHeader = req.getHeader("If");
if (ifHeader == null)
ifHeader = "";
if (debug > 1)
log("Delete:" + path);
- if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) ||
- (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) {
+ // Prevent deletion of special subdirectories
+ if (isSpecialPath(path)) {
errorList.put(path, new Integer(WebdavStatus.SC_FORBIDDEN));
return;
}
Vector<String> propertiesVector) {
// Exclude any resource in the /WEB-INF and /META-INF subdirectories
- // (the "toUpperCase()" avoids problems on Windows systems)
- if (path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF") ||
- path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))
+ if (isSpecialPath(path))
return;
CacheEntry cacheEntry = resources.lookupCache(path);
Vector<String> propertiesVector) {
// Exclude any resource in the /WEB-INF and /META-INF subdirectories
- // (the "toUpperCase()" avoids problems on Windows systems)
- if (path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF") ||
- path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))
+ if (isSpecialPath(path))
return;
// Retrieving the lock associated with the lock-null resource