From d58105b2c6120a10dff7a6742ebbe24ebcf25298 Mon Sep 17 00:00:00 2001 From: Kyle Larose Date: Wed, 15 Feb 2023 15:49:24 -0500 Subject: [PATCH] path-escape lockroot We ran in to an issue with various microsoft products accessing files over WebDAV which contain `%` characters in the name. The requests are all properly escaped -- e.g. the `%` is replaced with `%25`. Further the basic list functionality of the propfind responses contain encoded urls. The lock response/discovery includes the URL (lockroot) to the locked file. The existing implementation does not path escape that url. This seems to cause problems with the microsoft applications. When faced with the unencoded response, they try to lock again and fail. One explanation for this behaviour is that they maintain a table of locks indexed by encoded url. When the response from the server doesn't align with the URL they locked, the application fails. Update the lock discovery response code to escape the lockroot so that it matches everything else. --- webdav/xml.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/webdav/xml.go b/webdav/xml.go index fbd43cf220..8eda4b0a96 100644 --- a/webdav/xml.go +++ b/webdav/xml.go @@ -13,6 +13,7 @@ import ( "fmt" "io" "net/http" + "net/url" "time" // As of https://go-review.googlesource.com/#/c/12772/ which was submitted @@ -87,6 +88,10 @@ func writeLockInfo(w io.Writer, token string, ld LockDetails) (int, error) { depth = "0" } timeout := ld.Duration / time.Second + // PathEscape the root. Any URLs in this response body should match data on the wire + // meaning if a request came in escaped (which it should have), it should go out that + // way as well. + root := url.PathEscape(ld.Root) return fmt.Fprintf(w, "\n"+ "\n"+ " \n"+ @@ -97,7 +102,7 @@ func writeLockInfo(w io.Writer, token string, ld LockDetails) (int, error) { " %s\n"+ " %s\n"+ "", - depth, ld.OwnerXML, timeout, escape(token), escape(ld.Root), + depth, ld.OwnerXML, timeout, escape(token), escape(root), ) }