Skip to content

fix(ocdav): encode oc:downloadURL path so filenames with "%" round-trip - #653

Merged
rhafer merged 1 commit into
opencloud-eu:mainfrom
michaelstingl:fix/2852-downloadurl-encoding
Jun 3, 2026
Merged

rhafer merged 1 commit into
opencloud-eu:mainfrom
michaelstingl:fix/2852-downloadurl-encoding

Conversation

@michaelstingl

@michaelstingl michaelstingl commented May 31, 2026 •

Copy link
Copy Markdown

Description

PROPFIND builds the oc:downloadURL property with url.JoinPath, which treats a literal % in a filename as an escape. A name like firstword%20secondword.pdf is read as firstword secondword.pdf, so the web "Download" button requests the wrong path and the download returns 404 from personal/space storage. The sibling href in the same response uses net.EncodePath and stays correct, so PROPFIND already emits a correct href next to an under-encoded oc:downloadURL.

The fix uses net.EncodePath(path), the encoder the href already uses, in downloadURL (internal/http/services/owncloud/ocdav/propfind/propfind.go). url.JoinPath was introduced here to keep a literal # working (see #415); net.EncodePath covers both # -> %23 and % -> %25, so it keeps that behavior while letting names with reserved characters round-trip. The GET handler and the proxy are unchanged; only the URL this property emits was wrong.

Related Issue

Motivation and Context

A file whose name contains a literal % cannot be downloaded from personal or space storage via the web UI, although it lists and opens normally. Public links are unaffected: the public-files handler resolves the file by share token and emits no oc:downloadURL.

How Has This Been Tested?

  • test environment: reva main, Go 1.26, local
  • go build, go vet, go test ./...propfind/... and .../net/..., and the pinned golangci-lint v2.10.1 (make lint): all pass, 0 lint issues
  • the fix, unit: new ginkgo DescribeTable for downloadURL asserts a literal % encodes to %25 (whether or not followed by hex digits), # to %23, a plain space to %20
  • the fix, over HTTP: on a local revad stack, patched vs unpatched, PROPFIND of a public link to a file named firstword%20secondword.pdf emits an oc:downloadURL ending ...firstword%2520secondword.pdf with the fix and ...firstword%20secondword.pdf without it

Screenshots (if appropriate):

n/a. Server-side URL-encoding fix.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests only (no source changes)

Checklist:

  • Code changes
  • Unit tests added
  • Acceptance tests added (the behat suite has no download-of-a-name-with-reserved-characters scenario; this PR covers it at the unit level. A behat scenario can follow in the opencloud repo.)
  • Documentation added (n/a — reva generates the changelog from the PR title + Type:* label via ready-release-go; no fragment needed)

🤖 drafted with Claude Code, reviewed before submitting.

downloadURL built the path with url.JoinPath, which unescapes its input, so a
filename containing a literal "%" (e.g. "%20") collapsed (e.g. to a space) and
the download returned 404 while the resource href stayed correct. Use
net.EncodePath — the same encoder the href uses — which escapes "%"->"%25"
and "#"->"%23" so reserved characters round-trip.

Fixes: opencloud-eu/opencloud#2852
@micbar

micbar commented Jun 1, 2026

Copy link
Copy Markdown
Member

Please remove the changelog item. We are using ready-release-go from woodpecker.

@michaelstingl
michaelstingl force-pushed the fix/2852-downloadurl-encoding branch from f86dda6 to 3fccfa3 Compare June 1, 2026 08:26
@michaelstingl

Copy link
Copy Markdown
Author

@micbar done, removed the changelog commit. The fix commit is unchanged.

🤖 drafted with Claude Code, reviewed before submitting.

@rhafer
rhafer merged commit f97586c into opencloud-eu:main Jun 3, 2026
21 checks passed
@openclouders openclouders mentioned this pull request Jun 3, 2026
1 task
@michaelstingl
michaelstingl deleted the fix/2852-downloadurl-encoding branch June 25, 2026 15:55
michaelstingl added a commit to michaelstingl/opencloud-eu-opencloud that referenced this pull request Jul 7, 2026
… its oc:downloadURL

A file whose name contains a literal "%" 404s on download because the
server-built oc:downloadURL did not percent-encode the path (opencloud-eu#2852, fixed in
reva by opencloud-eu/reva#653). Add a scenario mirroring
the web client download flow: read the oc:downloadURL from PROPFIND and GET it
as-is (the signature in the URL authenticates it), asserting 200 and the content.

The new step "user X downloads the P file via its oc:downloadURL" lives in
WebDavPropertiesContext; a regex annotation avoids the ":" in oc:downloadURL
colliding with the turnip :placeholder syntax.

Verified red->green on posix and decomposed: red on an opencloud built on a reva
with the fix reverted (the download 404s), green on the shipped reva.

opencloud-eu#2852
michaelstingl added a commit to michaelstingl/opencloud-eu-opencloud that referenced this pull request Jul 7, 2026
… its oc:downloadURL

A file whose name contains a literal "%" 404s on download because the
server-built oc:downloadURL did not percent-encode the path (opencloud-eu#2852, fixed in
reva by opencloud-eu/reva#653). Add a scenario mirroring
the web client download flow: read the oc:downloadURL from PROPFIND and GET it
as-is (the signature in the URL authenticates it), asserting 200 and the content.

The new step "user X downloads the P file via its oc:downloadURL" lives in
WebDavPropertiesContext; a regex annotation avoids the ":" in oc:downloadURL
colliding with the turnip :placeholder syntax.

Verified red->green on posix and decomposed: red on an opencloud built on a reva
with the fix reverted (the download 404s), green on the shipped reva.

opencloud-eu#2852
v-scharf pushed a commit to michaelstingl/opencloud-eu-opencloud that referenced this pull request Jul 17, 2026
… its oc:downloadURL

A file whose name contains a literal "%" 404s on download because the
server-built oc:downloadURL did not percent-encode the path (opencloud-eu#2852, fixed in
reva by opencloud-eu/reva#653). Add a scenario mirroring
the web client download flow: read the oc:downloadURL from PROPFIND and GET it
as-is (the signature in the URL authenticates it), asserting 200 and the content.

The new step "user X downloads the P file via its oc:downloadURL" lives in
WebDavPropertiesContext; a regex annotation avoids the ":" in oc:downloadURL
colliding with the turnip :placeholder syntax.

Verified red->green on posix and decomposed: red on an opencloud built on a reva
with the fix reverted (the download 404s), green on the shipped reva.

opencloud-eu#2852
v-scharf pushed a commit to opencloud-eu/opencloud that referenced this pull request Jul 17, 2026
… its oc:downloadURL (#3079)

A file whose name contains a literal "%" 404s on download because the
server-built oc:downloadURL did not percent-encode the path (#2852, fixed in
reva by opencloud-eu/reva#653). Add a scenario mirroring
the web client download flow: read the oc:downloadURL from PROPFIND and GET it
as-is (the signature in the URL authenticates it), asserting 200 and the content.

The new step "user X downloads the P file via its oc:downloadURL" lives in
WebDavPropertiesContext; a regex annotation avoids the ":" in oc:downloadURL
colliding with the turnip :placeholder syntax.

Verified red->green on posix and decomposed: red on an opencloud built on a reva
with the fix reverted (the download 404s), green on the shipped reva.

#2852
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cannot download files that have "%20" in their filename.

3 participants