WebDAV

Added: WebDAV has been re-added. It is now written in XQuery and runs as a RESTXQ application; the Milton library is not required anymore.

WebDAV presents your databases as a file system. Databases are shown as the top-level folders, and the resources they contain can be browsed, opened, edited and deleted with any WebDAV client: a file manager, an XML editor such as oXygen, or a command-line tool.

The service is part of the standard web application and is available after startup via http://localhost:8080/webdav/.

Configuration

The service is a RESTXQ application, and its modules are located in the webdav directory of the web application path. It can be disabled by deleting this directory.

It is registered in the web.xml file with its own servlet class, and it is mapped to the /webdav/* path:

<servlet-mapping>
  <servlet-name>WebDAV</servlet-name>
  <url-pattern>/webdav/*</url-pattern>
</servlet-mapping>

The paths of the WebDAV modules include the servlet mapping, e.g. %rest:path("/webdav/{$path=.*}"). This is why the service is registered with org.basex.http.webdav.WebDAVServlet: other RESTXQ applications are matched against the request path below the servlet mapping, whereas this servlet matches the full path, including the mapping. If the service shall be mapped to a different path, the annotations in the webdav directory need to be adjusted accordingly.

Authentication

Unlike the other services of the standard web application, WebDAV authenticates its clients. It is registered in the web.xml file with an empty default user, so that credentials are always requested:

<servlet>
  <servlet-name>WebDAV</servlet-name>
  <servlet-class>org.basex.http.webdav.WebDAVServlet</servlet-class>
  <init-param>
    <param-name>org.basex.user</param-name>
    <param-value/>
  </init-param>
</servlet>

Clients are authenticated against the registered database users. If a user name is assigned to the org.basex.user parameter, it will be applied to all requests, and no credentials will be requested. The parameter is specific to a servlet, so other RESTXQ applications are not affected.

The authentication method is Basic by default. It can be changed with the AUTHMETHOD option, or with an org.basex.authmethod init parameter in the servlet entry. If Digest is chosen, the passwords of the users must be available as digest hashes: the AUTHALGORITHMS option needs to include the digest algorithm, as requests will otherwise be rejected with a 401 status code, no matter which credentials are supplied. The auth-int quality of protection is not offered, as it requires the full request body to be kept in main memory.

Access is granted according to the permissions of the authenticated user. Denied requests are answered with a 403 status code:

Permission Operations
read Browsing and downloading resources.
write Creating, changing and deleting resources and folders in an existing database.
create Creating and deleting a database, i.e. a folder at the top level.

A client that deletes a database recursively will therefore delete its contents and leave an empty database behind if the user has no create permission.

Clients

The service can be addressed with any WebDAV client. Some clients need to be prepared before they can be used:

Client Notes
oXygen XML Editor Add a new data source connection of type WebDAV, and point it to the URI of the service.
Windows Explorer By default, Windows refuses to send credentials via Basic Authentication over unencrypted connections. Either use HTTPS, or set the registry key HKLM\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\BasicAuthLevel to 2. The maximum size of a single upload is limited to 50 MB; it can be raised with the FileSizeLimitInBytes key in the same location.
macOS Finder Connect to the server with GoConnect to Server, and enter the URI with its http:// prefix. The webdav:// prefix is not understood by Finder. Additional ._ resources will be created, in which Finder stores its own metadata.
GNOME Files Choose Other Locations, and enter the URI with a dav:// prefix.
KDE Dolphin, Konqueror Enter the URI with a webdav:// prefix.

The size of XML documents is not reported, as it could only be determined by serializing the full document. Clients that expect a size for every file may refuse to open such a document.

Conventions

BaseX has no directories: the path of a resource is a single string. Folders are therefore derived from the resource paths in a database. A folder without resources cannot be represented this way, so an empty .empty resource is created to keep it alive. This resource is hidden from all listings.

URI Meaning
/webdav Collection of all databases.
/webdav/db Database db.
/webdav/db/path/to/doc.xml Resource path/to/doc.xml in database db.
/webdav/db/path Folder, if the database contains resources starting with path/.

Resources are stored in the format that matches their content: input that can be parsed as XML becomes an XML document, everything else is stored as a binary resource. A resource that is created directly below the root becomes a new database, named after the file without its suffix. Uploading example.xml to /webdav will thus create a database example.

If a database contains both a resource a and resources below a/, the resource takes precedence and the folder will be invisible. WebDAV cannot represent both at the same path.

A database is never replaced as a whole: if the target of a COPY or MOVE request is a database, its existing resources are kept, and only the resources of the request are added or replaced.

Browsing

RFC 4918 does not define what a GET request on a collection returns: it may be an index.html resource, a human-readable view, or something else entirely. WebDAV clients enumerate the members of a collection with PROPFIND.

BaseX returns a listing that can be browsed with a web browser. It shows the members of a collection, with their content type, size and timestamp, and links to the enclosing collections. The listing is a convenience: it is generated by html.xqm, and it can be adjusted or removed without affecting any WebDAV client.

Supported Methods

Method Description
OPTIONS Announces the supported methods and the WebDAV compliance classes.
PROPFIND Returns the live properties of a resource and, depending on the Depth header, of its members.
PROPPATCH Rejects the modification of properties. Every property is reported with a 403 status code in the multistatus response.
GET, HEAD Returns the contents of a resource. For collections, a browsable listing is generated (see Browsing).
PUT Stores a resource.
DELETE Deletes a resource, a folder or a database.
MKCOL Creates a folder or a database.
COPY, MOVE Copies or moves a resource or folder to the URI given in the Destination header. An existing target is replaced, unless the Overwrite header is set to F; the request is then rejected with a 412 status code. A folder cannot be moved or copied onto an existing resource, as a database cannot hold a resource and a folder of the same name; such a request is rejected with a 409 status code. COPY observes the Depth header: with a depth of 0, a folder is copied without its members.
LOCK, UNLOCK Acquires, refreshes and releases write locks.

A resource or folder can only be created if its parent folder exists. If it does not, the request is rejected with a 409 status code, and the folder needs to be created first with MKCOL.

The service is compliant with WebDAV classes 1 and 2. Dead properties are not supported: only the live properties listed below are available. PROPPATCH requests are answered with a multistatus response in which every property is rejected. The method is not declined altogether, as clients use it to attach their own metadata to a resource: Windows Explorer deletes an uploaded file again if the request fails. Requests with methods that are not implemented are rejected with a 405 status code and an Allow header.

The body of a PUT request is stored as an XML document if it can be parsed as XML, and as binary data otherwise. The content type announced by the client is ignored: many clients derive it from the file extension, and some send a probe request with a single byte before the actual data.

Properties

Property Description
displayname Name of the resource.
creationdate, getlastmodified Timestamp of the resource, or of the database for folders.
resourcetype Empty for resources, collection for databases and folders.
getcontenttype, getetag Media type and entity tag of a resource.
getcontentlength Size of a resource in bytes. The property is omitted for XML documents, for which BaseX reports the number of nodes instead of a byte count.
supportedlock, lockdiscovery Supported lock types, and the locks that apply to the resource.

Locking

Updated: Locks are kept in main memory; the ~webdav database is not used anymore.

Write locks are supported with a depth of 0 or infinity. A lock on a collection applies to all of its members: a client that does not supply the lock token in the If header will receive a 423 status code.

Locking a path that does not exist yet creates an empty resource. This allows clients to reserve a name before they write to it, which is what file managers do when a new file is created.

A lock will be granted for the number of seconds requested in the Timeout header, up to a maximum of one week. If no timeout is requested, the lock will be valid for one hour. Expired locks are discarded whenever a new lock is requested, and all locks on a resource are released when it is deleted or moved.

An exclusive lock can only be held by a single client, and only its own token gives access to the resource. A shared lock can be held by several clients at the same time; a request that modifies the resource must supply the token of one of them.

Only state tokens are evaluated in the If header. Conditions on entity tags, tagged lists and Not are ignored. A request that supplies a lock which does not apply to the resource is rejected with a 412 status code.

Locks are kept in main memory. They are shared by all clients and sessions, and they are discarded when the server is restarted.

Conditional Requests

PUT and DELETE requests observe the If-Match and If-None-Match headers. A request whose condition is not met is rejected with a 412 status code, and the addressed resource is left untouched:

Header Meaning
If-Match: "…" Perform the request only if the resource still has one of the supplied entity tags. Editors use this to ensure that a resource has not been changed since it was opened.
If-None-Match: * Perform the request only if the resource does not exist yet.

Several entity tags can be supplied as a comma-separated list. Weak tags (W/"…") are accepted by If-None-Match, but they never satisfy If-Match.

Changelog

Version 13.0
  • Added: WebDAV is now written in XQuery and runs as a RESTXQ application.
  • Updated: Locks are kept in main memory; the ~webdav database is not used anymore.
Version 12.0
  • Removed: WebDAV was dropped from the standard distributions.
Version 7.7Version 7.0
  • Added: WebDAV API introduced

⚡Generated with XQuery