From 4615343b730f177e349d1478e11bb1b8a9d8fc9f Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Wed, 2 Oct 2019 09:54:36 +0100 Subject: [PATCH] premiumizeme: use lib/encoder --- backend/premiumizeme/premiumizeme.go | 39 ++++++++-------------------- docs/content/premiumizeme.md | 13 ++++++++++ fs/encodings/encodings.go | 12 +++++++++ 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/backend/premiumizeme/premiumizeme.go b/backend/premiumizeme/premiumizeme.go index 4a2d5b18c..3e9fb3409 100644 --- a/backend/premiumizeme/premiumizeme.go +++ b/backend/premiumizeme/premiumizeme.go @@ -2,9 +2,7 @@ // object storage system. package premiumizeme -/* FIXME -escaping needs fixing - +/* Run of rclone info stringNeedsEscaping = []rune{ 0x00, 0x0A, 0x0D, 0x22, 0x2F, 0x5C, 0xBF, 0xFE @@ -36,6 +34,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 +46,8 @@ import ( "golang.org/x/oauth2" ) +const enc = encodings.PremiumizeMe + const ( rcloneClientID = "658922194" rcloneEncryptedClientSecret = "B5YIvQoRIhcpAYs8HYeyjb9gK-ftmZEbqdh_gNfc4RgO9Q" @@ -170,24 +171,6 @@ func shouldRetry(resp *http.Response, err error) (bool, error) { return fserrors.ShouldRetry(err) || fserrors.ShouldRetryHTTP(resp, retryErrorCodes), err } -// substitute reserved characters -func replaceReservedChars(x string) string { - // Backslash for FULLWIDTH REVERSE SOLIDUS - x = strings.Replace(x, "\\", "\", -1) - // Double quote for FULLWIDTH QUOTATION MARK - x = strings.Replace(x, `"`, """, -1) - return x -} - -// restore reserved characters -func restoreReservedChars(x string) string { - // FULLWIDTH QUOTATION MARK for Double quote - x = strings.Replace(x, """, `"`, -1) - // FULLWIDTH REVERSE SOLIDUS for Backslash - x = strings.Replace(x, "\", "\\", -1) - return x -} - // readMetaDataForPath reads the metadata from the path func (f *Fs) readMetaDataForPath(ctx context.Context, path string, directoriesOnly bool, filesOnly bool) (info *api.Item, err error) { // defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err) @@ -381,7 +364,7 @@ func (f *Fs) CreateDir(ctx context.Context, pathID, leaf string) (newID string, Path: "/folder/create", Parameters: f.baseParams(), MultipartParams: url.Values{ - "name": {replaceReservedChars(leaf)}, + "name": {enc.FromStandardName(leaf)}, "parent_id": {pathID}, }, } @@ -446,7 +429,7 @@ func (f *Fs) listAll(ctx context.Context, dirID string, directoriesOnly bool, fi fs.Debugf(f, "Ignoring %q - unknown type %q", item.Name, item.Type) continue } - item.Name = restoreReservedChars(item.Name) + item.Name = enc.ToStandardName(item.Name) if fn(item) { found = true break @@ -654,8 +637,8 @@ func (f *Fs) Purge(ctx context.Context) error { // between directories and a separate one to rename them. We try to // call the minimum number of API calls. func (f *Fs) move(ctx context.Context, isFile bool, id, oldLeaf, newLeaf, oldDirectoryID, newDirectoryID string) (err error) { - newLeaf = replaceReservedChars(newLeaf) - oldLeaf = replaceReservedChars(oldLeaf) + newLeaf = enc.FromStandardName(newLeaf) + oldLeaf = enc.FromStandardName(oldLeaf) doRenameLeaf := oldLeaf != newLeaf doMove := oldDirectoryID != newDirectoryID @@ -686,7 +669,7 @@ func (f *Fs) move(ctx context.Context, isFile bool, id, oldLeaf, newLeaf, oldDir } else { opts.MultipartParams.Set("folders[]", id) } - //replacedLeaf := replaceReservedChars(leaf) + //replacedLeaf := enc.FromStandardName(leaf) var resp *http.Response var result api.Response err = f.pacer.Call(func() (bool, error) { @@ -908,7 +891,7 @@ func (o *Object) Remote() string { // srvPath returns a path for use in server func (o *Object) srvPath() string { - return replaceReservedChars(o.fs.rootSlash() + o.remote) + return enc.FromStandardPath(o.fs.rootSlash() + o.remote) } // Hash returns the SHA-1 of an object returning a lowercase hex string @@ -1023,7 +1006,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op if err != nil { return err } - leaf = replaceReservedChars(leaf) + leaf = enc.FromStandardName(leaf) var resp *http.Response var info api.FolderUploadinfoResponse diff --git a/docs/content/premiumizeme.md b/docs/content/premiumizeme.md index 4afa97e9a..dc3532521 100644 --- a/docs/content/premiumizeme.md +++ b/docs/content/premiumizeme.md @@ -88,6 +88,19 @@ premiumize.me does not support modification times or hashes, therefore syncing will default to `--size-only` checking. Note that using `--update` will work. +#### Restricted filename characters + +In addition to the [default restricted characters set](/overview/#restricted-characters) +the following characters are also replaced: + +| Character | Value | Replacement | +| --------- |:-----:|:-----------:| +| \ | 0x5C | \ | +| " | 0x22 | " | + +Invalid UTF-8 bytes will also be [replaced](/overview/#invalid-utf8), +as they can't be used in JSON strings. + ### Standard Options diff --git a/fs/encodings/encodings.go b/fs/encodings/encodings.go index d00ac02a1..3ee5f5882 100644 --- a/fs/encodings/encodings.go +++ b/fs/encodings/encodings.go @@ -219,6 +219,15 @@ const OpenDrive = encoder.MultiEncoder( encoder.EncodeRightSpace | encoder.EncodeInvalidUtf8) +// PremiumizeMe is the encoding used by the premiumizeme backend +// +// Encode invalid UTF-8 bytes as json doesn't handle them properly. +const PremiumizeMe = encoder.MultiEncoder( + uint(Display) | + encoder.EncodeBackSlash | + encoder.EncodeDoubleQuote | + encoder.EncodeInvalidUtf8) + // Pcloud is the encoding used by the pcloud backend // // Encode invalid UTF-8 bytes as json doesn't handle them properly. @@ -359,6 +368,8 @@ func ByName(name string) encoder.Encoder { return OneDrive case "opendrive": return OpenDrive + case "premiumizeme": + return PremiumizeMe case "pcloud": return Pcloud case "qingstor": @@ -405,6 +416,7 @@ func Names() []string { "mega", "onedrive", "opendrive", + "premiumizeme", "pcloud", "sharefile", }