WebDAV hrefs not URL-encoded when 'exported' via vandelay

Issue Description

Following the migration guide, I imported the FileNodes via WebDAV.

This leads to the root folder (which stalwart names based on the account’s display name) being imported as a FileNode. For user accounts this regularly contains characters that have to be URL-encoded, such as spaces or diacritics.

When exporting this FileNode tree to a current stalwart server, this root folder is created. (The fact that this modifies the directory tree by inserting the root node as a sub node is a separate issue). When querying the stalwart server via e.g.
curl -u [email protected] -X PROPFIND https://api.example.com/dav/file/[email protected]/ | yq -p xml -o xml, stalwart returns a filenode for the root node with

href: /dav/file/admin%40example.com/
display name: System administrator

as well as a filenode with

href: /dav/file/admin%40example.com/System administrator/
display name: System administrator

Note that while the @ is correctly escaped with %40 in the relative href path, the space in System administrator is not.

I assume that vandelay creates the FileNodes via the JMAP API.

Expected Behavior

FileNodes imported by vandelay via WebDAV and exported to a new server are correctly escaped in the WebDAV API.

Actual Behavior

FileNodes imported by vandelay via WebDAV and exported to a new server are not escaped in the WebDAV API.

Reproduction Steps

  1. Setup stalwart v0.15.x server A
  2. Import directory tree of the ‘System administrator’ account using vandelay from server A
  3. Setup stalwart v0.16.x server B
  4. Export directory tree to the ‘System administrator’ account on server B
  5. Query WebDAV using e.g. curl (see above)

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

Directory Backend

Internal

Additional Context

Before posting, I have searched for the term ‘vandelay webdav’ and did not identify any related issues.

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

Root cause confirmed in the source. DavResources builds hrefs with only the account name component percent‑encoded, not the per‑resource path segments:

  • base_path (e.g. [email protected]) is escaped with percent_encoding::utf8_percent_encode(..., RFC_3986) when the cache is built (crates/groupware/src/cache/file.rs, cache/calcard.rs).
  • But the actual folder/file names that make up resource.path.path are concatenated raw in DavResources::format_resource, format_collection, and format_item (crates/common/src/storage/dav.rs):
pub fn format_resource(&self, resource: DavResourcePath<'_>) -> String {
    if resource.resource.is_container() {
        format!("{}{}/", self.base_path, resource.path.path)
    } else {
        format!("{}{}", self.base_path, resource.path.path)
    }
}

Since resource.path.path is built directly from container/file names (e.g. in build_nested_hierarchy) without any percent-encoding step, any space, diacritic, or other reserved character in a folder/file name (like the imported root folder named System administrator) ends up unescaped in the returned href, while the account name portion of base_path is correctly escaped. This is consistent with what you observed: %40 in the account segment but a literal space further down the path.

This is a genuine bug in the WebDAV href generation, not something you can work around via Vandelay import options. I’ve grounded this from the current server source, but I can’t confirm from docs whether a fix is already staged; a maintainer will need to weigh in on that.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Fixed in the vandelay repo .

I believe that these are separate issues. While this issue was surfaced due to vandelay automatically creating a directory including a space, stalwart should URL-encode paths that were created via JMAP when exposing via WebDAV. Otherwise it remains possible to create paths via JMAP FileNode that are inaccessible via WebDAV due to missing URL-encoding.