mirror of
https://github.com/rclone/rclone.git
synced 2024-11-25 09:41:44 +08:00
sharefile: use lib/encoder
This commit is contained in:
parent
5cef5f8b49
commit
b581f2de26
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
Translate file names for sharefile
|
||||
*/
|
||||
|
||||
package sharefile
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// charMap holds replacements for characters
|
||||
//
|
||||
// Sharefile has a restricted set of characters compared to other
|
||||
// cloud storage systems, so we to map these to the FULLWIDTH unicode
|
||||
// equivalents
|
||||
//
|
||||
// http://unicode-search.net/unicode-namesearch.pl?term=SOLIDUS
|
||||
var (
|
||||
charMap = map[rune]rune{
|
||||
'\\': '\', // FULLWIDTH REVERSE SOLIDUS
|
||||
'*': '*', // FULLWIDTH ASTERISK
|
||||
'<': '<', // FULLWIDTH LESS-THAN SIGN
|
||||
'>': '>', // FULLWIDTH GREATER-THAN SIGN
|
||||
'?': '?', // FULLWIDTH QUESTION MARK
|
||||
':': ':', // FULLWIDTH COLON
|
||||
'|': '|', // FULLWIDTH VERTICAL LINE
|
||||
'"': '"', // FULLWIDTH QUOTATION MARK
|
||||
'.': '.', // FULLWIDTH FULL STOP
|
||||
' ': '␠', // SYMBOL FOR SPACE
|
||||
}
|
||||
invCharMap map[rune]rune
|
||||
fixStartingWithPeriod = regexp.MustCompile(`(/|^)\.`)
|
||||
fixEndingWithPeriod = regexp.MustCompile(`\.(/|$)`)
|
||||
fixStartingWithSpace = regexp.MustCompile(`(/|^) `)
|
||||
fixEndingWithSpace = regexp.MustCompile(` (/|$)`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Create inverse charMap
|
||||
invCharMap = make(map[rune]rune, len(charMap))
|
||||
for k, v := range charMap {
|
||||
invCharMap[v] = k
|
||||
}
|
||||
}
|
||||
|
||||
// replaceReservedChars takes a path and substitutes any reserved
|
||||
// characters in it
|
||||
func replaceReservedChars(in string) string {
|
||||
// Names can't start with a period '.'
|
||||
in = fixStartingWithPeriod.ReplaceAllString(in, "$1"+string(charMap['.']))
|
||||
// Names can't end with a period '.'
|
||||
in = fixEndingWithPeriod.ReplaceAllString(in, string(charMap['.'])+"$1")
|
||||
// Names can't start with space
|
||||
in = fixStartingWithSpace.ReplaceAllString(in, "$1"+string(charMap[' ']))
|
||||
// Names can't end with space
|
||||
in = fixEndingWithSpace.ReplaceAllString(in, string(charMap[' '])+"$1")
|
||||
// Replace reserved characters
|
||||
return strings.Map(func(c rune) rune {
|
||||
if replacement, ok := charMap[c]; ok && c != '.' && c != '~' && c != ' ' {
|
||||
return replacement
|
||||
}
|
||||
return c
|
||||
}, in)
|
||||
}
|
||||
|
||||
// restoreReservedChars takes a path and undoes any substitutions
|
||||
// made by replaceReservedChars
|
||||
func restoreReservedChars(in string) string {
|
||||
return strings.Map(func(c rune) rune {
|
||||
if replacement, ok := invCharMap[c]; ok {
|
||||
return replacement
|
||||
}
|
||||
return c
|
||||
}, in)
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package sharefile
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestReplace(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
in string
|
||||
out string
|
||||
}{
|
||||
{"", ""},
|
||||
{"abc 123", "abc 123"},
|
||||
{`\*<>?:|#%".~`, `\*<>?:|#%".~`},
|
||||
{`\*<>?:|#%".~/\*<>?:|#%".~`, `\*<>?:|#%".~/\*<>?:|#%".~`},
|
||||
{" leading space", "␠leading space"},
|
||||
{"trailing space ", "trailing space␠"},
|
||||
{".leading dot", ".leading dot"},
|
||||
{"trailing dot.", "trailing dot."},
|
||||
{" leading space/ leading space/ leading space", "␠leading space/␠leading space/␠leading space"},
|
||||
{"trailing dot./trailing dot./trailing dot.", "trailing dot./trailing dot./trailing dot."},
|
||||
{".leading dot/..leading dot/.leading dot", ".leading dot/..leading dot/.leading dot"},
|
||||
} {
|
||||
got := replaceReservedChars(test.in)
|
||||
if got != test.out {
|
||||
t.Errorf("replaceReservedChars(%q) want %q got %q", test.in, test.out, got)
|
||||
}
|
||||
got2 := restoreReservedChars(got)
|
||||
if got2 != test.in {
|
||||
t.Errorf("restoreReservedChars(%q) want %q got %q", got, test.in, got2)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -90,6 +90,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/hash"
|
||||
"github.com/rclone/rclone/lib/dircache"
|
||||
|
@ -100,6 +101,8 @@ import (
|
|||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const enc = encodings.Sharefile
|
||||
|
||||
const (
|
||||
rcloneClientID = "djQUPlHTUM9EvayYBWuKC5IrVIoQde46"
|
||||
rcloneEncryptedClientSecret = "v7572bKhUindQL3yDnUAebmgP-QxiwT38JLxVPolcZBl6SSs329MtFzH73x7BeELmMVZtneUPvALSopUZ6VkhQ"
|
||||
|
@ -298,7 +301,7 @@ func (f *Fs) readMetaDataForIDPath(ctx context.Context, id, path string, directo
|
|||
}
|
||||
if path != "" {
|
||||
opts.Path += "/ByPath"
|
||||
opts.Parameters.Set("path", "/"+replaceReservedChars(path))
|
||||
opts.Parameters.Set("path", "/"+enc.FromStandardPath(path))
|
||||
}
|
||||
var item api.Item
|
||||
var resp *http.Response
|
||||
|
@ -592,7 +595,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) {
|
||||
var resp *http.Response
|
||||
leaf = replaceReservedChars(leaf)
|
||||
leaf = enc.FromStandardName(leaf)
|
||||
var req = api.Item{
|
||||
Name: leaf,
|
||||
FileName: leaf,
|
||||
|
@ -661,7 +664,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
|
||||
|
@ -870,7 +873,7 @@ func (f *Fs) updateItem(ctx context.Context, id, leaf, directoryID string, modTi
|
|||
"overwrite": {"false"},
|
||||
},
|
||||
}
|
||||
leaf = replaceReservedChars(leaf)
|
||||
leaf = enc.FromStandardName(leaf)
|
||||
// FIXME this appears to be a bug in the API
|
||||
//
|
||||
// If you set the modified time via PATCH then the server
|
||||
|
@ -1116,7 +1119,7 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (dst fs.Obj
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
srcLeaf = replaceReservedChars(srcLeaf)
|
||||
srcLeaf = enc.FromStandardName(srcLeaf)
|
||||
_ = srcParentID
|
||||
|
||||
// Create temporary object
|
||||
|
@ -1124,7 +1127,7 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (dst fs.Obj
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dstLeaf = replaceReservedChars(dstLeaf)
|
||||
dstLeaf = enc.FromStandardName(dstLeaf)
|
||||
|
||||
sameName := strings.ToLower(srcLeaf) == strings.ToLower(dstLeaf)
|
||||
if sameName && srcParentID == dstParentID {
|
||||
|
@ -1387,7 +1390,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 req = api.UploadRequest{
|
||||
Method: "standard",
|
||||
Raw: true,
|
||||
|
|
|
@ -302,6 +302,18 @@ const QingStor = encoder.MultiEncoder(
|
|||
encoder.EncodeCtl |
|
||||
encoder.EncodeSlash)
|
||||
|
||||
// Sharefile is the encoding used by the sharefile backend
|
||||
const Sharefile = encoder.MultiEncoder(
|
||||
uint(Base) |
|
||||
encoder.EncodeWin | // :?"*<>|
|
||||
encoder.EncodeBackSlash | // \
|
||||
encoder.EncodeCtl |
|
||||
encoder.EncodeRightSpace |
|
||||
encoder.EncodeRightPeriod |
|
||||
encoder.EncodeLeftSpace |
|
||||
encoder.EncodeLeftPeriod |
|
||||
encoder.EncodeInvalidUtf8)
|
||||
|
||||
// ByName returns the encoder for a give backend name or nil
|
||||
func ByName(name string) encoder.Encoder {
|
||||
switch strings.ToLower(name) {
|
||||
|
@ -353,6 +365,8 @@ func ByName(name string) encoder.Encoder {
|
|||
return QingStor
|
||||
case "s3":
|
||||
return S3
|
||||
case "sharefile":
|
||||
return Sharefile
|
||||
//case "sftp":
|
||||
case "swift":
|
||||
return Swift
|
||||
|
@ -392,5 +406,6 @@ func Names() []string {
|
|||
"onedrive",
|
||||
"opendrive",
|
||||
"pcloud",
|
||||
"sharefile",
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user