forked from TrueCloudLab/rclone
putio: use lib/encoder
And in the process - fix a bug with + and & in file name - fix NewObject returning directories as files
This commit is contained in:
parent
4615343b73
commit
fd51f24906
6 changed files with 54 additions and 9 deletions
|
@ -145,7 +145,7 @@ func (f *Fs) CreateDir(ctx context.Context, pathID, leaf string) (newID string,
|
||||||
var entry putio.File
|
var entry putio.File
|
||||||
err = f.pacer.Call(func() (bool, error) {
|
err = f.pacer.Call(func() (bool, error) {
|
||||||
// fs.Debugf(f, "creating folder. part: %s, parentID: %d", leaf, parentID)
|
// fs.Debugf(f, "creating folder. part: %s, parentID: %d", leaf, parentID)
|
||||||
entry, err = f.client.Files.CreateFolder(ctx, leaf, parentID)
|
entry, err = f.client.Files.CreateFolder(ctx, enc.FromStandardName(leaf), parentID)
|
||||||
return shouldRetry(err)
|
return shouldRetry(err)
|
||||||
})
|
})
|
||||||
return itoa(entry.ID), err
|
return itoa(entry.ID), err
|
||||||
|
@ -172,11 +172,11 @@ func (f *Fs) FindLeaf(ctx context.Context, pathID, leaf string) (pathIDOut strin
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, child := range children {
|
for _, child := range children {
|
||||||
if child.Name == leaf {
|
if enc.ToStandardName(child.Name) == leaf {
|
||||||
found = true
|
found = true
|
||||||
pathIDOut = itoa(child.ID)
|
pathIDOut = itoa(child.ID)
|
||||||
if !child.IsDir() {
|
if !child.IsDir() {
|
||||||
err = fs.ErrorNotAFile
|
err = fs.ErrorIsFile
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, child := range children {
|
for _, child := range children {
|
||||||
remote := path.Join(dir, child.Name)
|
remote := path.Join(dir, enc.ToStandardName(child.Name))
|
||||||
// fs.Debugf(f, "child: %s", remote)
|
// fs.Debugf(f, "child: %s", remote)
|
||||||
if child.IsDir() {
|
if child.IsDir() {
|
||||||
f.dirCache.Put(remote, itoa(child.ID))
|
f.dirCache.Put(remote, itoa(child.ID))
|
||||||
|
@ -292,7 +292,7 @@ func (f *Fs) createUpload(ctx context.Context, name string, size int64, parentID
|
||||||
req = req.WithContext(ctx) // go1.13 can use NewRequestWithContext
|
req = req.WithContext(ctx) // go1.13 can use NewRequestWithContext
|
||||||
req.Header.Set("tus-resumable", "1.0.0")
|
req.Header.Set("tus-resumable", "1.0.0")
|
||||||
req.Header.Set("upload-length", strconv.FormatInt(size, 10))
|
req.Header.Set("upload-length", strconv.FormatInt(size, 10))
|
||||||
b64name := base64.StdEncoding.EncodeToString([]byte(name))
|
b64name := base64.StdEncoding.EncodeToString([]byte(enc.FromStandardName(name)))
|
||||||
b64true := base64.StdEncoding.EncodeToString([]byte("true"))
|
b64true := base64.StdEncoding.EncodeToString([]byte("true"))
|
||||||
b64parentID := base64.StdEncoding.EncodeToString([]byte(parentID))
|
b64parentID := base64.StdEncoding.EncodeToString([]byte(parentID))
|
||||||
b64modifiedAt := base64.StdEncoding.EncodeToString([]byte(modTime.Format(time.RFC3339)))
|
b64modifiedAt := base64.StdEncoding.EncodeToString([]byte(modTime.Format(time.RFC3339)))
|
||||||
|
@ -505,7 +505,7 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (o fs.Objec
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Set("file_id", strconv.FormatInt(srcObj.file.ID, 10))
|
params.Set("file_id", strconv.FormatInt(srcObj.file.ID, 10))
|
||||||
params.Set("parent_id", directoryID)
|
params.Set("parent_id", directoryID)
|
||||||
params.Set("name", leaf)
|
params.Set("name", enc.FromStandardName(leaf))
|
||||||
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/copy", strings.NewReader(params.Encode()))
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/copy", strings.NewReader(params.Encode()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -544,7 +544,7 @@ func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (o fs.Objec
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Set("file_id", strconv.FormatInt(srcObj.file.ID, 10))
|
params.Set("file_id", strconv.FormatInt(srcObj.file.ID, 10))
|
||||||
params.Set("parent_id", directoryID)
|
params.Set("parent_id", directoryID)
|
||||||
params.Set("name", leaf)
|
params.Set("name", enc.FromStandardName(leaf))
|
||||||
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/move", strings.NewReader(params.Encode()))
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/move", strings.NewReader(params.Encode()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -633,7 +633,7 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Set("file_id", srcID)
|
params.Set("file_id", srcID)
|
||||||
params.Set("parent_id", dstDirectoryID)
|
params.Set("parent_id", dstDirectoryID)
|
||||||
params.Set("name", leaf)
|
params.Set("name", enc.FromStandardName(leaf))
|
||||||
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/move", strings.NewReader(params.Encode()))
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/move", strings.NewReader(params.Encode()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
|
@ -137,7 +137,7 @@ func (o *Object) readEntry(ctx context.Context) (f *putio.File, err error) {
|
||||||
}
|
}
|
||||||
err = o.fs.pacer.Call(func() (bool, error) {
|
err = o.fs.pacer.Call(func() (bool, error) {
|
||||||
// fs.Debugf(o, "requesting child. directoryID: %s, name: %s", directoryID, leaf)
|
// fs.Debugf(o, "requesting child. directoryID: %s, name: %s", directoryID, leaf)
|
||||||
req, err := o.fs.client.NewRequest(ctx, "GET", "/v2/files/"+directoryID+"/child?name="+url.PathEscape(leaf), nil)
|
req, err := o.fs.client.NewRequest(ctx, "GET", "/v2/files/"+directoryID+"/child?name="+url.QueryEscape(enc.FromStandardName(leaf)), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,12 @@ func (o *Object) readEntry(ctx context.Context) (f *putio.File, err error) {
|
||||||
}
|
}
|
||||||
return shouldRetry(err)
|
return shouldRetry(err)
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if resp.File.IsDir() {
|
||||||
|
return nil, fs.ErrorNotAFile
|
||||||
|
}
|
||||||
return &resp.File, err
|
return &resp.File, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,25 @@ import (
|
||||||
"github.com/rclone/rclone/fs"
|
"github.com/rclone/rclone/fs"
|
||||||
"github.com/rclone/rclone/fs/config/configmap"
|
"github.com/rclone/rclone/fs/config/configmap"
|
||||||
"github.com/rclone/rclone/fs/config/obscure"
|
"github.com/rclone/rclone/fs/config/obscure"
|
||||||
|
"github.com/rclone/rclone/fs/encodings"
|
||||||
"github.com/rclone/rclone/lib/dircache"
|
"github.com/rclone/rclone/lib/dircache"
|
||||||
"github.com/rclone/rclone/lib/oauthutil"
|
"github.com/rclone/rclone/lib/oauthutil"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TestPutio
|
||||||
|
stringNeedsEscaping = []rune{
|
||||||
|
'/', '\x00'
|
||||||
|
}
|
||||||
|
maxFileLength = 255
|
||||||
|
canWriteUnnormalized = true
|
||||||
|
canReadUnnormalized = true
|
||||||
|
canReadRenormalized = true
|
||||||
|
canStream = false
|
||||||
|
*/
|
||||||
|
const enc = encodings.Putio
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const (
|
const (
|
||||||
rcloneClientID = "4131"
|
rcloneClientID = "4131"
|
||||||
|
|
|
@ -96,5 +96,17 @@ To copy a local directory to a put.io directory called backup
|
||||||
|
|
||||||
rclone copy /home/source remote:backup
|
rclone copy /home/source remote:backup
|
||||||
|
|
||||||
|
#### Restricted filename characters
|
||||||
|
|
||||||
|
In addition to the [default restricted characters set](/overview/#restricted-characters)
|
||||||
|
the following characters are also replaced:
|
||||||
|
|
||||||
|
| Character | Value | Replacement |
|
||||||
|
| --------- |:-----:|:-----------:|
|
||||||
|
| \ | 0x5C | \ |
|
||||||
|
|
||||||
|
Invalid UTF-8 bytes will also be [replaced](/overview/#invalid-utf8),
|
||||||
|
as they can't be used in JSON strings.
|
||||||
|
|
||||||
<!--- autogenerated options start - DO NOT EDIT, instead edit fs.RegInfo in backend/putio/putio.go then run make backenddocs -->
|
<!--- autogenerated options start - DO NOT EDIT, instead edit fs.RegInfo in backend/putio/putio.go then run make backenddocs -->
|
||||||
<!--- autogenerated options stop -->
|
<!--- autogenerated options stop -->
|
||||||
|
|
|
@ -238,6 +238,16 @@ const Pcloud = encoder.MultiEncoder(
|
||||||
encoder.EncodeBackSlash |
|
encoder.EncodeBackSlash |
|
||||||
encoder.EncodeInvalidUtf8)
|
encoder.EncodeInvalidUtf8)
|
||||||
|
|
||||||
|
// Putio is the encoding used by the putio backend
|
||||||
|
//
|
||||||
|
// Note that \ is renamed to -
|
||||||
|
//
|
||||||
|
// Encode invalid UTF-8 bytes as json doesn't handle them properly.
|
||||||
|
const Putio = encoder.MultiEncoder(
|
||||||
|
uint(Display) |
|
||||||
|
encoder.EncodeBackSlash |
|
||||||
|
encoder.EncodeInvalidUtf8)
|
||||||
|
|
||||||
// Fichier is the encoding used by the fichier backend
|
// Fichier is the encoding used by the fichier backend
|
||||||
//
|
//
|
||||||
// Characters that need escaping
|
// Characters that need escaping
|
||||||
|
|
|
@ -29,8 +29,11 @@ const (
|
||||||
OneDrive = Base
|
OneDrive = Base
|
||||||
OpenDrive = Base
|
OpenDrive = Base
|
||||||
Pcloud = Base
|
Pcloud = Base
|
||||||
|
PremiumizeMe = Base
|
||||||
|
Putio = Base
|
||||||
QingStor = Base
|
QingStor = Base
|
||||||
S3 = Base
|
S3 = Base
|
||||||
|
Sharefile = Base
|
||||||
Swift = Base
|
Swift = Base
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue