Skip to content

Commit

Permalink
feature (ftps): add FTPs #169
Browse files Browse the repository at this point in the history
  • Loading branch information
mickael-kerjean committed Jul 1, 2019
1 parent 8d84ce2 commit d2e9424
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 4 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<p align="center">
A Dropbox-like file manager that let you manage your data anywhere it is located:<br>
FTP • SFTP • WebDAV • Git • S3 • LDAP • Mysql <br>
FTP • FTPS • SFTP • WebDAV • Git • S3 • LDAP • Mysql <br>
CardDAV • CalDAV • Backblaze B2 • Minio <br>
Dropbox • Google Drive
</p>
Expand Down Expand Up @@ -45,9 +45,9 @@
</p>

# Documentation
- [Getting started](https://www.filestash.app/docs)
- [Installation](https://www.filestash.app/docs/install-and-upgrade)
- [FAQ](https://www.filestash.app/docs/faq)
- [Getting started](https://www.filestash.app/docs/)
- [Installation](https://www.filestash.app/docs/install-and-upgrade/)
- [FAQ](https://www.filestash.app/docs/faq/)

# Support the project
- Bitcoin: `3LX5KGmSmHDj5EuXrmUvcg77EJxCxmdsgW`
Expand Down
1 change: 1 addition & 0 deletions server/plugin/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_backblaze"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_dav"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_mysql"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_ftps"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_scanner"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_svg"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_handler_console"
Expand Down
204 changes: 204 additions & 0 deletions server/plugin/plg_backend_ftps/index.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package plg_backend_ftps

import (
"fmt"
. "github.com/mickael-kerjean/filestash/server/common"
"github.com/secsy/goftp"
"io"
"os"
"regexp"
"strconv"
"strings"
"time"
)

var FtpsCache AppCache

type Ftps struct {
client *goftp.Client
}

func init() {
Backend.Register("ftps", Ftps{})

FtpsCache = NewAppCache(2, 1)
FtpsCache.OnEvict(func(key string, value interface{}) {
c := value.(*Ftps)
c.Close()
})
}

func (f Ftps) Init(params map[string]string, app *App) (IBackend, error) {
if c := FtpsCache.Get(params); c != nil {
d := c.(*Ftps)
return d, nil
}
if params["hostname"] == "" {
params["hostname"] = "localhost"
}
if params["port"] == "" {
params["port"] = "21"
}
if params["username"] == "" {
params["username"] = "anonymous"
}
if params["username"] == "anonymous" && params["password"] == "" {
params["password"] = "anonymous"
}

conn := 5
if params["conn"] != "" {
if i, err := strconv.Atoi(params["conn"]); err == nil && i > 0 {
conn = i
}
}

config := goftp.Config{
User: params["username"],
Password: params["password"],
ConnectionsPerHost: conn,
Timeout: 10 * time.Second,
TLSMode: goftp.TLSImplicit,
}
client, err := goftp.DialConfig(config, fmt.Sprintf("%s:%s", params["hostname"], params["port"]))
if err != nil {
return nil, err
}
backend := Ftps{client}

FtpsCache.Set(params, &backend)
return backend, nil
}

func (f Ftps) LoginForm() Form {
return Form{
Elmnts: []FormElement{
FormElement{
Name: "type",
Type: "hidden",
Value: "ftps",
},
FormElement{
Name: "hostname",
Type: "text",
Placeholder: "Hostname*",
},
FormElement{
Name: "username",
Type: "text",
Placeholder: "Username",
},
FormElement{
Name: "password",
Type: "password",
Placeholder: "Password",
},
FormElement{
Name: "advanced",
Type: "enable",
Placeholder: "Advanced",
Target: []string{"ftps_path", "ftps_port", "ftps_conn"},
},
FormElement{
Id: "ftps_path",
Name: "path",
Type: "text",
Placeholder: "Path",
},
FormElement{
Id: "ftps_port",
Name: "port",
Type: "number",
Placeholder: "Port",
},
FormElement{
Id: "ftps_conn",
Name: "conn",
Type: "number",
Placeholder: "Number of connections",
},
},
}
}

func (f Ftps) Home() (string, error) {
return f.client.Getwd()
}

func (f Ftps) Ls(path string) ([]os.FileInfo, error) {
return f.client.ReadDir(path)
}

func (f Ftps) Cat(path string) (io.ReadCloser, error) {
pr, pw := io.Pipe()
go func() {
if err := f.client.Retrieve(path, pw); err != nil {
pr.CloseWithError(NewError("Problem", 409))
}
pw.Close()
}()
return pr, nil
}

func (f Ftps) Mkdir(path string) error {
_, err := f.client.Mkdir(path)
return err
}

func (f Ftps) Rm(path string) error {
isDirectory := func(p string) bool {
return regexp.MustCompile(`\/$`).MatchString(p)
}
transformError := func(e error) error {
// For some reasons bsftp is struggling with the library
// sometimes returning a 200 OK
if e == nil {
return nil
}
if obj, ok := e.(goftp.Error); ok {
if obj.Code() < 300 && obj.Code() > 0 {
return nil
}
}
return e
}
if isDirectory(path) {
entries, err := f.Ls(path)
if transformError(err) != nil {
return err
}
for _, entry := range entries {
if entry.IsDir() {
err = f.Rm(path + entry.Name() + "/")
if transformError(err) != nil {
return err
}
} else {
err = f.Rm(path + entry.Name())
if transformError(err) != nil {
return err
}
}
}
err = f.client.Rmdir(path)
return transformError(err)
}
err := f.client.Delete(path)
return transformError(err)
}

func (f Ftps) Mv(from string, to string) error {
return f.client.Rename(from, to)
}

func (f Ftps) Touch(path string) error {
return f.client.Store(path, strings.NewReader(""))
}

func (f Ftps) Save(path string, file io.Reader) error {
return f.client.Store(path, file)
}

func (f Ftps) Close() error {
return f.client.Close()
}

0 comments on commit d2e9424

Please sign in to comment.