Updated FTP to follow SFTP standards, updated documentation

This commit is contained in:
Sjur Fredriksen 2017-05-25 00:24:46 +02:00 committed by Nick Craig-Wood
parent cfc5f7bb2d
commit ade61fa756
5 changed files with 70 additions and 51 deletions

View file

@ -40,7 +40,7 @@ var Root = &cobra.Command{
Short: "Sync files and directories to and from local and remote object stores - " + fs.Version, Short: "Sync files and directories to and from local and remote object stores - " + fs.Version,
Long: ` Long: `
Rclone is a command line program to sync files and directories to and Rclone is a command line program to sync files and directories to and
from various cloud storage systems, such as: from various cloud storage systems and using file transfer services, such as:
* Google Drive * Google Drive
* Amazon S3 * Amazon S3
@ -52,6 +52,8 @@ from various cloud storage systems, such as:
* Hubic * Hubic
* Backblaze B2 * Backblaze B2
* Yandex Disk * Yandex Disk
* SFTP
* FTP
* The local filesystem * The local filesystem
Features Features

View file

@ -7,7 +7,7 @@ date: "2017-01-01"
<i class="fa fa-file"></i> FTP <i class="fa fa-file"></i> FTP
------------------------------ ------------------------------
FTP is the File Transfer Protocl. FTP support is provided using the FTP is the File Transfer Protocol. FTP support is provided using the
[github.com/jlaffaye/ftp](https://godoc.org/github.com/jlaffaye/ftp) [github.com/jlaffaye/ftp](https://godoc.org/github.com/jlaffaye/ftp)
package. package.
@ -15,12 +15,10 @@ Here is an example of making an FTP configuration. First run
rclone config rclone config
This will guide you through an interactive setup process. An FTP This will guide you through an interactive setup process. An FTP remote only
backend only needs an URL and username and password. With needs a host together with and a username and a password. With anonymous FTP
anonymous FTP server, you will need to use `anonymous` as username and server, you will need to use `anonymous` as username and your email address as
your email address as the password. If you want to use a non-standard FTP the password.
port, please specify this with a colon and the port number at the end of
the URL. For example `ftp://ftp.mirrorservice.org:5555`
``` ```
No remotes found - make a new one No remotes found - make a new one
@ -43,7 +41,7 @@ Choose a number from below, or type in your own value
\ "dropbox" \ "dropbox"
5 / Encrypt/Decrypt a remote 5 / Encrypt/Decrypt a remote
\ "crypt" \ "crypt"
6 / FTP interface 6 / FTP Connection
\ "ftp" \ "ftp"
7 / Google Cloud Storage (this is not Google Drive) 7 / Google Cloud Storage (this is not Google Drive)
\ "google cloud storage" \ "google cloud storage"
@ -62,9 +60,16 @@ Choose a number from below, or type in your own value
14 / Yandex Disk 14 / Yandex Disk
\ "yandex" \ "yandex"
Storage> ftp Storage> ftp
Username FTP host to connect to
username> anonymous Choose a number from below, or type in your own value
Password 1 / Connect to ftp.example.com
\ "ftp.example.com"
host> ftp.example.com
FTP username, leave blank for current username, ncw
user>
FTP port, leave blank to use default (21)
port>
FTP password
y) Yes type in my own password y) Yes type in my own password
g) Generate random password g) Generate random password
y/g> y y/g> y
@ -72,14 +77,13 @@ Enter the password:
password: password:
Confirm the password: Confirm the password:
password: password:
FTP URL
url> ftp://ftp.mirrorservice.org/
Remote config Remote config
-------------------- --------------------
[remote] [remote]
username = anonymous host = ftp.example.com
password = *** ENCRYPTED *** user =
url = ftp://ftp.mirrorservice.org/ port =
pass = *** ENCRYPTED ***
-------------------- --------------------
y) Yes this is OK y) Yes this is OK
e) Edit this remote e) Edit this remote

View file

@ -45,23 +45,25 @@ Choose a number from below, or type in your own value
\ "dropbox" \ "dropbox"
5 / Encrypt/Decrypt a remote 5 / Encrypt/Decrypt a remote
\ "crypt" \ "crypt"
6 / Google Cloud Storage (this is not Google Drive) 6 / FTP Connection
\ "ftp"
7 / Google Cloud Storage (this is not Google Drive)
\ "google cloud storage" \ "google cloud storage"
7 / Google Drive 8 / Google Drive
\ "drive" \ "drive"
8 / Hubic 9 / Hubic
\ "hubic" \ "hubic"
9 / Local Disk 10 / Local Disk
\ "local" \ "local"
10 / Microsoft OneDrive 11 / Microsoft OneDrive
\ "onedrive" \ "onedrive"
11 / Openstack Swift (Rackspace Cloud Files, Memset Memstore, OVH) 12 / Openstack Swift (Rackspace Cloud Files, Memset Memstore, OVH)
\ "swift" \ "swift"
12 / SSH/SFTP Connection 13 / SSH/SFTP Connection
\ "sftp" \ "sftp"
13 / Yandex Disk 14 / Yandex Disk
\ "yandex" \ "yandex"
Storage> 12 Storage> sftp
SSH host to connect to SSH host to connect to
Choose a number from below, or type in your own value Choose a number from below, or type in your own value
1 / Connect to example.com 1 / Connect to example.com
@ -69,7 +71,7 @@ Choose a number from below, or type in your own value
host> example.com host> example.com
SSH username, leave blank for current username, ncw SSH username, leave blank for current username, ncw
user> user>
SSH port SSH port, leave blank to use default (22)
port> port>
SSH password, leave blank to use ssh-agent SSH password, leave blank to use ssh-agent
y) Yes type in my own password y) Yes type in my own password

View file

@ -5,8 +5,8 @@ import (
"io" "io"
"net/textproto" "net/textproto"
"net/url" "net/url"
"os"
"path" "path"
"strings"
"sync" "sync"
"time" "time"
@ -19,19 +19,30 @@ import (
func init() { func init() {
fs.Register(&fs.RegInfo{ fs.Register(&fs.RegInfo{
Name: "ftp", Name: "ftp",
Description: "FTP interface", Description: "FTP Connection",
NewFs: NewFs, NewFs: NewFs,
Options: []fs.Option{ Options: []fs.Option{
{ {
Name: "username", Name: "host",
Help: "Username", Help: "FTP host to connect to",
Optional: false,
Examples: []fs.OptionExample{{
Value: "ftp.example.com",
Help: "Connect to ftp.example.com",
}},
}, { }, {
Name: "password", Name: "user",
Help: "Password", Help: "FTP username, leave blank for current username, " + os.Getenv("USER"),
Optional: true,
}, {
Name: "port",
Help: "FTP port, leave blank to use default (21) ",
Optional: true,
}, {
Name: "pass",
Help: "FTP password",
IsPassword: true, IsPassword: true,
}, { Optional: false,
Name: "url",
Help: "FTP URL",
}, },
}, },
}) })
@ -147,27 +158,27 @@ func (f *Fs) putFtpConnection(pc **ftp.ServerConn, err error) {
// NewFs contstructs an Fs from the path, container:path // NewFs contstructs an Fs from the path, container:path
func NewFs(name, root string) (ff fs.Fs, err error) { func NewFs(name, root string) (ff fs.Fs, err error) {
// defer fs.Trace(nil, "name=%q, root=%q", name, root)("fs=%v, err=%v", &ff, &err) // defer fs.Trace(nil, "name=%q, root=%q", name, root)("fs=%v, err=%v", &ff, &err)
URL := fs.ConfigFileGet(name, "url") host := fs.ConfigFileGet(name, "host")
user := fs.ConfigFileGet(name, "username") user := fs.ConfigFileGet(name, "user")
pass := fs.ConfigFileGet(name, "password") pass := fs.ConfigFileGet(name, "pass")
port := fs.ConfigFileGet(name, "port")
pass, err = fs.Reveal(pass) pass, err = fs.Reveal(pass)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "NewFS decrypt password") return nil, errors.Wrap(err, "NewFS decrypt password")
} }
u, err := url.Parse(URL) if user == "" {
user = os.Getenv("USER")
}
if port == "" {
port = "21"
}
dialAddr := host + ":" + port
u, err := url.Parse("ftp://" + dialAddr)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "NewFS URL parse") return nil, errors.Wrap(err, "NewFS URL parse")
} }
urlPath := strings.Trim(u.Path, "/")
fullPath := root
if urlPath != "" && !strings.HasPrefix("/", root) {
fullPath = path.Join(u.Path, root)
}
root = fullPath
dialAddr := u.Host
if strings.IndexRune(dialAddr, ':') < 0 {
dialAddr += ":21"
}
f := &Fs{ f := &Fs{
name: name, name: name,
root: root, root: root,

View file

@ -38,7 +38,7 @@ func init() {
Optional: true, Optional: true,
}, { }, {
Name: "port", Name: "port",
Help: "SSH port", Help: "SSH port, leave blank to use default (22)",
Optional: true, Optional: true,
}, { }, {
Name: "pass", Name: "pass",