webdav: support put.io #580

* Add docs on how to set up
  * Fix the listing routine
    * Use Depth: 1 in otherwise we get a recursive listing
    * Detect collections properly rather than relying on them ending in /
    * Add / to collection URLs which don't have one
This commit is contained in:
Nick Craig-Wood 2017-10-23 12:13:01 +01:00
parent 683befaec1
commit 6df1f6fad1
4 changed files with 52 additions and 8 deletions

View File

@ -35,6 +35,7 @@ Rclone is a command line program to sync files and directories to and from:
* {{< provider name="Oracle Cloud Storage" home="https://cloud.oracle.com/storage-opc" config="/swift/" >}}
* {{< provider name="Ownloud" home="https://owncloud.org/" config="/webdav/#owncloud" >}}
* {{< provider name="pCloud" home="https://www.pcloud.com/" config="/pcloud/" >}}
* {{< provider name="put.io" home="https://put.io/" config="/webdav/#put-io" >}}
* {{< provider name="QingStor" home="https://www.qingcloud.com/products/storage" config="/qingstor/" >}}
* {{< provider name="Rackspace Cloud Files" home="https://www.rackspace.com/cloud/files" config="/swift/" >}}
* {{< provider name="SFTP" home="https://en.wikipedia.org/wiki/SFTP" config="/sftp/" >}}

View File

@ -146,3 +146,28 @@ Nextcloud does not support streaming of files (`rcat`) whereas
Owncloud does. This [may be
fixed](https://github.com/nextcloud/nextcloud-snap/issues/365) in the
future.
## Put.io ##
put.io can be accessed in a read only way using webdav.
Configure the `url` as `https://webdav.put.io` and use your normal
account username and password for `user` and `pass`. Set the `vendor`
to `other`.
Your config file should end up looking like this:
```
[putio]
type = webdav
url = https://webdav.put.io
vendor = other
user = YourUserName
pass = encryptedpassword
```
If you are using `put.io` with `rclone mount` then use the
`--read-only` flag to signal to the OS that it can't write to the
mount.
For more help see [the put.io webdav docs](http://help.put.io/apps-and-integrations/ftp-and-webdav).

View File

@ -26,11 +26,11 @@ type Response struct {
// Prop is the properties of a response
type Prop struct {
Status string `xml:"DAV: status"`
Name string `xml:"DAV: prop>displayname,omitempty"`
Type xml.Name `xml:"DAV: prop>resourcetype>collection,omitempty"`
Size int64 `xml:"DAV: prop>getcontentlength,omitempty"`
Modified Time `xml:"DAV: prop>getlastmodified,omitempty"`
Status string `xml:"DAV: status"`
Name string `xml:"DAV: prop>displayname,omitempty"`
Type *xml.Name `xml:"DAV: prop>resourcetype>collection,omitempty"`
Size int64 `xml:"DAV: prop>getcontentlength,omitempty"`
Modified Time `xml:"DAV: prop>getlastmodified,omitempty"`
}
// Parse a status of the form "HTTP/1.1 200 OK",

View File

@ -360,6 +360,9 @@ func (f *Fs) listAll(dir string, directoriesOnly bool, filesOnly bool, fn listAl
opts := rest.Opts{
Method: "PROPFIND",
Path: f.dirPath(dir), // FIXME Should not start with /
ExtraHeaders: map[string]string{
"Depth": "1",
},
}
var result api.Multistatus
var resp *http.Response
@ -384,8 +387,19 @@ func (f *Fs) listAll(dir string, directoriesOnly bool, filesOnly bool, fn listAl
for i := range result.Responses {
item := &result.Responses[i]
// Collections must end in /
isDir := strings.HasSuffix(item.Href, "/")
// Figure out what this is
isDir := false
if t := item.Props.Type; t != nil {
// When a client sees a resourcetype it
// doesn't recognize it should assume it is a
// regular non-collection resource. [WebDav
// book by Lisa Dusseault ch 7.5.8 p170]
if t.Space == "DAV:" && t.Local == "collection" {
isDir = true
} else {
fs.Debugf(nil, "Unknown resource type %q/%q on %q", t.Space, t.Local, item.Props.Name)
}
}
// Find name
u, err := rest.URLJoin(baseURL, item.Href)
@ -393,8 +407,12 @@ func (f *Fs) listAll(dir string, directoriesOnly bool, filesOnly bool, fn listAl
fs.Errorf(nil, "URL Join failed for %q and %q: %v", baseURL, item.Href, err)
continue
}
// Make sure directories end with a /
if isDir {
u.Path = addSlash(u.Path)
}
if !strings.HasPrefix(u.Path, baseURL.Path) {
fs.Debugf(nil, "Item with unknown path received: %q, %q", item.Href, u.Path)
fs.Debugf(nil, "Item with unknown path received: %q, %q", u.Path, baseURL.Path)
continue
}
remote := path.Join(dir, u.Path[len(baseURL.Path):])