diff --git a/backend/drive/drive.go b/backend/drive/drive.go index 59c09fa2c..d0af425a5 100644 --- a/backend/drive/drive.go +++ b/backend/drive/drive.go @@ -32,6 +32,7 @@ import ( "github.com/rclone/rclone/fs/config/configmap" "github.com/rclone/rclone/fs/config/configstruct" "github.com/rclone/rclone/fs/config/obscure" + "github.com/rclone/rclone/fs/encodings" "github.com/rclone/rclone/fs/fserrors" "github.com/rclone/rclone/fs/fshttp" "github.com/rclone/rclone/fs/hash" @@ -47,6 +48,8 @@ import ( "google.golang.org/api/googleapi" ) +const enc = encodings.Drive + // Constants const ( rcloneClientID = "202264815644.apps.googleusercontent.com" @@ -599,11 +602,10 @@ func (f *Fs) list(ctx context.Context, dirIDs []string, title string, directorie } var stems []string if title != "" { + searchTitle := enc.FromStandardName(title) // Escaping the backslash isn't documented but seems to work - searchTitle := strings.Replace(title, `\`, `\\`, -1) + searchTitle = strings.Replace(searchTitle, `\`, `\\`, -1) searchTitle = strings.Replace(searchTitle, `'`, `\'`, -1) - // Convert / to / for search - searchTitle = strings.Replace(searchTitle, "/", "/", -1) var titleQuery bytes.Buffer _, _ = fmt.Fprintf(&titleQuery, "(name='%s'", searchTitle) @@ -671,11 +673,9 @@ OUTER: return false, errors.Wrap(err, "couldn't list directory") } for _, item := range files.Files { - // Convert / to / for listing purposes - item.Name = strings.Replace(item.Name, "/", "/", -1) + item.Name = enc.ToStandardName(item.Name) // Check the case of items is correct since // the `=` operator is case insensitive. - if title != "" && title != item.Name { found := false for _, stem := range stems { @@ -1210,6 +1210,7 @@ func (f *Fs) FindLeaf(ctx context.Context, pathID, leaf string) (pathIDOut strin // CreateDir makes a directory with pathID as parent and name leaf func (f *Fs) CreateDir(ctx context.Context, pathID, leaf string) (newID string, err error) { + leaf = enc.FromStandardName(leaf) // fmt.Println("Making", path) // Define the metadata for the directory we are going to create. createInfo := &drive.File{ @@ -1645,6 +1646,7 @@ func (f *Fs) createFileInfo(ctx context.Context, remote string, modTime time.Tim return nil, err } + leaf = enc.FromStandardName(leaf) // Define the metadata for the file we are going to create. createInfo := &drive.File{ Name: leaf, @@ -2316,6 +2318,7 @@ func (f *Fs) changeNotifyRunner(ctx context.Context, notifyFunc func(string, fs. // find the new path if change.File != nil { + change.File.Name = enc.ToStandardName(change.File.Name) changeType := fs.EntryDirectory if change.File.MimeType != driveFolderType { changeType = fs.EntryObject diff --git a/docs/content/drive.md b/docs/content/drive.md index 3e094b2ce..c9c1d082e 100644 --- a/docs/content/drive.md +++ b/docs/content/drive.md @@ -355,6 +355,14 @@ large folder (10600 directories, 39000 files): Google drive stores modification times accurate to 1 ms. +#### Restricted filename characters + +Only Invalid UTF-8 bytes will be [replaced](/overview/#invalid-utf8), +as they can't be used in JSON strings. + +In contrast to other backends, `/` can also be used in names and `.` +or `..` are valid names. + ### Revisions ### Google drive stores revisions of files. When you upload a change to