From 1582a21408ab08db7dd94b9266e6b82dfa7c4f5a Mon Sep 17 00:00:00 2001 From: Cnly Date: Mon, 11 Mar 2019 16:30:38 +0800 Subject: [PATCH] onedrive: Always add trailing colon to path when addressing items - #2720, #3039 --- backend/onedrive/onedrive.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/backend/onedrive/onedrive.go b/backend/onedrive/onedrive.go index 21395f1ec..ba6eb8010 100644 --- a/backend/onedrive/onedrive.go +++ b/backend/onedrive/onedrive.go @@ -335,8 +335,13 @@ func shouldRetry(resp *http.Response, err error) (bool, error) { // readMetaDataForPathRelativeToID reads the metadata for a path relative to an item that is addressed by its normalized ID. // if `relPath` == "", it reads the metadata for the item with that ID. +// +// We address items using the pattern `drives/driveID/items/itemID:/relativePath` +// instead of simply using `drives/driveID/root:/itemPath` because it works for +// "shared with me" folders in OneDrive Personal (See #2536, #2778) +// This path pattern comes from https://github.com/OneDrive/onedrive-api-docs/issues/908#issuecomment-417488480 func (f *Fs) readMetaDataForPathRelativeToID(normalizedID string, relPath string) (info *api.Item, resp *http.Response, err error) { - opts := newOptsCall(normalizedID, "GET", ":/"+rest.URLPathEscape(replaceReservedChars(relPath))) + opts := newOptsCall(normalizedID, "GET", ":/"+withTrailingColon(rest.URLPathEscape(replaceReservedChars(relPath)))) err = f.pacer.Call(func() (bool, error) { resp, err = f.srv.CallJSON(&opts, nil, &info) return shouldRetry(resp, err) @@ -1340,12 +1345,12 @@ func (o *Object) setModTime(modTime time.Time) (*api.Item, error) { opts = rest.Opts{ Method: "PATCH", RootURL: rootURL, - Path: "/" + drive + "/items/" + trueDirID + ":/" + rest.URLPathEscape(leaf), + Path: "/" + drive + "/items/" + trueDirID + ":/" + withTrailingColon(rest.URLPathEscape(leaf)), } } else { opts = rest.Opts{ Method: "PATCH", - Path: "/root:/" + rest.URLPathEscape(o.srvPath()), + Path: "/root:/" + withTrailingColon(rest.URLPathEscape(o.srvPath())), } } update := api.SetFileSystemInfo{ @@ -1668,6 +1673,21 @@ func getRelativePathInsideBase(base, target string) (string, bool) { return "", false } +// Adds a ":" at the end of `remotePath` in a proper manner. +// If `remotePath` already ends with "/", change it to ":/" +// If `remotePath` is "", return "". +// A workaround for #2720 and #3039 +func withTrailingColon(remotePath string) string { + if remotePath == "" { + return "" + } + + if strings.HasSuffix(remotePath, "/") { + return remotePath[:len(remotePath)-1] + ":/" + } + return remotePath + ":" +} + // Check the interfaces are satisfied var ( _ fs.Fs = (*Fs)(nil)