Skip to content

Commit

Permalink
webdav: path-escape lockroot
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
klarose committed Feb 15, 2023
1 parent 8e2b117 commit c72303b
Showing 1 changed file with 6 additions and 1 deletion.
7 changes: 6 additions & 1 deletion webdav/xml.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"time"

// As of https://go-review.googlesource.com/#/c/12772/ which was submitted
Expand Down Expand Up @@ -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, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+
"<D:prop xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock>\n"+
" <D:locktype><D:write/></D:locktype>\n"+
Expand All @@ -97,7 +102,7 @@ func writeLockInfo(w io.Writer, token string, ld LockDetails) (int, error) {
" <D:locktoken><D:href>%s</D:href></D:locktoken>\n"+
" <D:lockroot><D:href>%s</D:href></D:lockroot>\n"+
"</D:activelock></D:lockdiscovery></D:prop>",
depth, ld.OwnerXML, timeout, escape(token), escape(ld.Root),
depth, ld.OwnerXML, timeout, escape(token), escape(root),
)
}

Expand Down

0 comments on commit c72303b

Please sign in to comment.