2017-03-22 18:09:21 +01:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-03-19 11:35:30 +01:00
|
|
|
"log"
|
2017-03-22 18:09:21 +01:00
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/dutchcoders/transfer.sh/server"
|
|
|
|
"github.com/fatih/color"
|
|
|
|
"github.com/minio/cli"
|
2019-03-18 20:52:38 +01:00
|
|
|
"google.golang.org/api/googleapi"
|
2017-03-22 18:09:21 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var Version = "0.1"
|
|
|
|
var helpTemplate = `NAME:
|
|
|
|
{{.Name}} - {{.Usage}}
|
|
|
|
|
|
|
|
DESCRIPTION:
|
|
|
|
{{.Description}}
|
|
|
|
|
|
|
|
USAGE:
|
|
|
|
{{.Name}} {{if .Flags}}[flags] {{end}}command{{if .Flags}}{{end}} [arguments...]
|
|
|
|
|
|
|
|
COMMANDS:
|
|
|
|
{{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
|
|
|
|
{{end}}{{if .Flags}}
|
|
|
|
FLAGS:
|
|
|
|
{{range .Flags}}{{.}}
|
|
|
|
{{end}}{{end}}
|
|
|
|
VERSION:
|
|
|
|
` + Version +
|
|
|
|
`{{ "\n"}}`
|
|
|
|
|
|
|
|
var globalFlags = []cli.Flag{
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "listener",
|
|
|
|
Usage: "127.0.0.1:8080",
|
|
|
|
Value: "127.0.0.1:8080",
|
|
|
|
},
|
|
|
|
// redirect to https?
|
|
|
|
// hostnames
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "profile-listener",
|
|
|
|
Usage: "127.0.0.1:6060",
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
cli.BoolFlag{
|
|
|
|
Name: "force-https",
|
|
|
|
Usage: "",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "tls-listener",
|
|
|
|
Usage: "127.0.0.1:8443",
|
|
|
|
Value: "",
|
|
|
|
},
|
2018-07-07 19:05:16 +02:00
|
|
|
cli.BoolFlag{
|
|
|
|
Name: "tls-listener-only",
|
|
|
|
Usage: "",
|
|
|
|
},
|
2017-03-22 18:09:21 +01:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "tls-cert-file",
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "tls-private-key",
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "temp-path",
|
|
|
|
Usage: "path to temp files",
|
|
|
|
Value: os.TempDir(),
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "web-path",
|
|
|
|
Usage: "path to static web files",
|
|
|
|
Value: "",
|
|
|
|
},
|
2019-03-30 12:35:57 +01:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "proxy-path",
|
|
|
|
Usage: "path prefix when service is run behind a proxy",
|
|
|
|
Value: "",
|
|
|
|
},
|
2018-06-26 18:39:56 +02:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "ga-key",
|
|
|
|
Usage: "key for google analytics (front end)",
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "uservoice-key",
|
|
|
|
Usage: "key for user voice (front end)",
|
|
|
|
Value: "",
|
|
|
|
},
|
2017-03-22 18:09:21 +01:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "provider",
|
2018-06-19 15:30:26 +02:00
|
|
|
Usage: "s3|gdrive|local",
|
2017-03-22 18:09:21 +01:00
|
|
|
Value: "",
|
|
|
|
},
|
2017-07-16 15:19:41 +02:00
|
|
|
cli.StringFlag{
|
2018-06-19 15:33:42 +02:00
|
|
|
Name: "s3-endpoint",
|
|
|
|
Usage: "",
|
|
|
|
Value: "http://s3-eu-west-1.amazonaws.com",
|
2017-07-16 15:19:41 +02:00
|
|
|
EnvVar: "S3_ENDPOINT",
|
|
|
|
},
|
2019-06-23 13:04:37 +02:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "s3-region",
|
|
|
|
Usage: "",
|
|
|
|
Value: "eu-west-1",
|
|
|
|
EnvVar: "S3_REGION",
|
|
|
|
},
|
2017-03-22 18:09:21 +01:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "aws-access-key",
|
|
|
|
Usage: "",
|
|
|
|
Value: "",
|
|
|
|
EnvVar: "AWS_ACCESS_KEY",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "aws-secret-key",
|
|
|
|
Usage: "",
|
|
|
|
Value: "",
|
|
|
|
EnvVar: "AWS_SECRET_KEY",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "bucket",
|
|
|
|
Usage: "",
|
|
|
|
Value: "",
|
|
|
|
EnvVar: "BUCKET",
|
|
|
|
},
|
2019-03-19 11:35:30 +01:00
|
|
|
cli.BoolFlag{
|
2019-03-19 18:48:28 +01:00
|
|
|
Name: "s3-no-multipart",
|
|
|
|
Usage: "Disables S3 Multipart Puts",
|
2019-03-19 11:35:30 +01:00
|
|
|
},
|
2018-06-19 15:30:26 +02:00
|
|
|
cli.StringFlag{
|
2018-07-07 20:23:50 +02:00
|
|
|
Name: "gdrive-client-json-filepath",
|
|
|
|
Usage: "",
|
|
|
|
Value: "",
|
2018-06-19 15:30:26 +02:00
|
|
|
},
|
|
|
|
cli.StringFlag{
|
2018-07-07 20:23:50 +02:00
|
|
|
Name: "gdrive-local-config-path",
|
|
|
|
Usage: "",
|
|
|
|
Value: "",
|
2018-06-19 15:30:26 +02:00
|
|
|
},
|
2019-03-18 20:52:38 +01:00
|
|
|
cli.IntFlag{
|
|
|
|
Name: "gdrive-chunk-size",
|
|
|
|
Usage: "",
|
2019-03-18 21:03:03 +01:00
|
|
|
Value: googleapi.DefaultUploadChunkSize / 1024 / 1024,
|
2019-03-18 20:52:38 +01:00
|
|
|
},
|
2017-03-28 17:08:34 +02:00
|
|
|
cli.IntFlag{
|
|
|
|
Name: "rate-limit",
|
|
|
|
Usage: "requests per minute",
|
|
|
|
Value: 0,
|
|
|
|
EnvVar: "",
|
|
|
|
},
|
2017-03-22 18:09:21 +01:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "lets-encrypt-hosts",
|
|
|
|
Usage: "host1, host2",
|
|
|
|
Value: "",
|
|
|
|
EnvVar: "HOSTS",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "log",
|
|
|
|
Usage: "/var/log/transfersh.log",
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "basedir",
|
|
|
|
Usage: "path to storage",
|
|
|
|
Value: "",
|
|
|
|
},
|
2017-03-22 23:13:34 +01:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "clamav-host",
|
|
|
|
Usage: "clamav-host",
|
|
|
|
Value: "",
|
|
|
|
EnvVar: "CLAMAV_HOST",
|
|
|
|
},
|
2017-03-22 23:14:01 +01:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "virustotal-key",
|
|
|
|
Usage: "virustotal-key",
|
|
|
|
Value: "",
|
|
|
|
EnvVar: "VIRUSTOTAL_KEY",
|
|
|
|
},
|
2017-03-22 18:09:21 +01:00
|
|
|
cli.BoolFlag{
|
|
|
|
Name: "profiler",
|
|
|
|
Usage: "enable profiling",
|
|
|
|
},
|
2018-06-23 18:46:28 +02:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "http-auth-user",
|
|
|
|
Usage: "user for http basic auth",
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "http-auth-pass",
|
|
|
|
Usage: "pass for http basic auth",
|
|
|
|
Value: "",
|
|
|
|
},
|
2019-05-11 14:42:59 +02:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "ip-whitelist",
|
|
|
|
Usage: "comma separated list of ips allowed to connect to the service",
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "ip-blacklist",
|
|
|
|
Usage: "comma separated list of ips not allowed to connect to the service",
|
|
|
|
Value: "",
|
|
|
|
},
|
2017-03-22 18:09:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type Cmd struct {
|
|
|
|
*cli.App
|
|
|
|
}
|
|
|
|
|
|
|
|
func VersionAction(c *cli.Context) {
|
|
|
|
fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh: Easy file sharing from the command line")))
|
|
|
|
}
|
|
|
|
|
|
|
|
func New() *Cmd {
|
2018-10-27 00:15:55 +02:00
|
|
|
logger := log.New(os.Stdout, "[transfer.sh]", log.LstdFlags)
|
|
|
|
|
2017-03-22 18:09:21 +01:00
|
|
|
app := cli.NewApp()
|
|
|
|
app.Name = "transfer.sh"
|
|
|
|
app.Author = ""
|
|
|
|
app.Usage = "transfer.sh"
|
|
|
|
app.Description = `Easy file sharing from the command line`
|
|
|
|
app.Flags = globalFlags
|
|
|
|
app.CustomAppHelpTemplate = helpTemplate
|
|
|
|
app.Commands = []cli.Command{
|
|
|
|
{
|
|
|
|
Name: "version",
|
|
|
|
Action: VersionAction,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
app.Before = func(c *cli.Context) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
app.Action = func(c *cli.Context) {
|
|
|
|
options := []server.OptionFn{}
|
|
|
|
if v := c.String("listener"); v != "" {
|
|
|
|
options = append(options, server.Listener(v))
|
|
|
|
}
|
|
|
|
|
2018-07-07 19:05:16 +02:00
|
|
|
if v := c.String("tls-listener"); v == "" {
|
|
|
|
} else if c.Bool("tls-listener-only") {
|
|
|
|
options = append(options, server.TLSListener(v, true))
|
|
|
|
} else {
|
|
|
|
options = append(options, server.TLSListener(v, false))
|
2017-03-22 18:09:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if v := c.String("profile-listener"); v != "" {
|
|
|
|
options = append(options, server.ProfileListener(v))
|
|
|
|
}
|
|
|
|
|
|
|
|
if v := c.String("web-path"); v != "" {
|
|
|
|
options = append(options, server.WebPath(v))
|
|
|
|
}
|
|
|
|
|
2019-03-30 12:35:57 +01:00
|
|
|
if v := c.String("proxy-path"); v != "" {
|
|
|
|
options = append(options, server.ProxyPath(v))
|
|
|
|
}
|
|
|
|
|
2018-06-26 18:39:56 +02:00
|
|
|
if v := c.String("ga-key"); v != "" {
|
|
|
|
options = append(options, server.GoogleAnalytics(v))
|
|
|
|
}
|
|
|
|
|
|
|
|
if v := c.String("uservoice-key"); v != "" {
|
|
|
|
options = append(options, server.UserVoice(v))
|
|
|
|
}
|
|
|
|
|
2017-03-22 18:09:21 +01:00
|
|
|
if v := c.String("temp-path"); v != "" {
|
|
|
|
options = append(options, server.TempPath(v))
|
|
|
|
}
|
|
|
|
|
2018-10-27 00:15:55 +02:00
|
|
|
if v := c.String("log"); v != "" {
|
|
|
|
options = append(options, server.LogFile(logger, v))
|
|
|
|
} else {
|
|
|
|
options = append(options, server.Logger(logger))
|
|
|
|
}
|
|
|
|
|
2017-03-22 18:09:21 +01:00
|
|
|
if v := c.String("lets-encrypt-hosts"); v != "" {
|
|
|
|
options = append(options, server.UseLetsEncrypt(strings.Split(v, ",")))
|
|
|
|
}
|
|
|
|
|
2017-03-22 23:14:01 +01:00
|
|
|
if v := c.String("virustotal-key"); v != "" {
|
|
|
|
options = append(options, server.VirustotalKey(v))
|
|
|
|
}
|
|
|
|
|
2017-03-22 23:13:34 +01:00
|
|
|
if v := c.String("clamav-host"); v != "" {
|
|
|
|
options = append(options, server.ClamavHost(v))
|
|
|
|
}
|
|
|
|
|
2017-03-28 17:08:34 +02:00
|
|
|
if v := c.Int("rate-limit"); v > 0 {
|
|
|
|
options = append(options, server.RateLimit(v))
|
|
|
|
}
|
|
|
|
|
2017-03-22 18:09:21 +01:00
|
|
|
if cert := c.String("tls-cert-file"); cert == "" {
|
|
|
|
} else if pk := c.String("tls-private-key"); pk == "" {
|
|
|
|
} else {
|
|
|
|
options = append(options, server.TLSConfig(cert, pk))
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Bool("profiler") {
|
|
|
|
options = append(options, server.EnableProfiler())
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Bool("force-https") {
|
|
|
|
options = append(options, server.ForceHTTPs())
|
|
|
|
}
|
|
|
|
|
2018-06-23 18:46:28 +02:00
|
|
|
if httpAuthUser := c.String("http-auth-user"); httpAuthUser == "" {
|
|
|
|
} else if httpAuthPass := c.String("http-auth-pass"); httpAuthPass == "" {
|
|
|
|
} else {
|
|
|
|
options = append(options, server.HttpAuthCredentials(httpAuthUser, httpAuthPass))
|
|
|
|
}
|
|
|
|
|
2019-05-11 14:42:59 +02:00
|
|
|
applyIPFilter := false
|
|
|
|
ipFilterOptions := server.IPFilterOptions{}
|
|
|
|
if ipWhitelist := c.String("ip-whitelist"); ipWhitelist != "" {
|
|
|
|
applyIPFilter = true
|
|
|
|
ipFilterOptions.AllowedIPs = strings.Split(ipWhitelist, ",")
|
|
|
|
ipFilterOptions.BlockByDefault = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if ipBlacklist := c.String("ip-blacklist"); ipBlacklist != "" {
|
|
|
|
applyIPFilter = true
|
|
|
|
ipFilterOptions.BlockedIPs = strings.Split(ipBlacklist, ",")
|
|
|
|
}
|
|
|
|
|
|
|
|
if applyIPFilter {
|
|
|
|
options = append(options, server.FilterOptions(ipFilterOptions))
|
|
|
|
}
|
|
|
|
|
2017-03-22 18:09:21 +01:00
|
|
|
switch provider := c.String("provider"); provider {
|
|
|
|
case "s3":
|
|
|
|
if accessKey := c.String("aws-access-key"); accessKey == "" {
|
|
|
|
panic("access-key not set.")
|
|
|
|
} else if secretKey := c.String("aws-secret-key"); secretKey == "" {
|
|
|
|
panic("secret-key not set.")
|
|
|
|
} else if bucket := c.String("bucket"); bucket == "" {
|
|
|
|
panic("bucket not set.")
|
2019-06-23 13:04:37 +02:00
|
|
|
} else if storage, err := server.NewS3Storage(accessKey, secretKey, bucket, c.String("s3-endpoint"), logger, c.Bool("s3-no-multipart"), c.String("s3-region")); err != nil {
|
2017-03-22 18:09:21 +01:00
|
|
|
panic(err)
|
|
|
|
} else {
|
|
|
|
options = append(options, server.UseStorage(storage))
|
|
|
|
}
|
2018-06-19 15:30:26 +02:00
|
|
|
case "gdrive":
|
2019-03-18 20:52:38 +01:00
|
|
|
chunkSize := c.Int("gdrive-chunk-size")
|
|
|
|
|
2018-06-19 15:30:26 +02:00
|
|
|
if clientJsonFilepath := c.String("gdrive-client-json-filepath"); clientJsonFilepath == "" {
|
|
|
|
panic("client-json-filepath not set.")
|
|
|
|
} else if localConfigPath := c.String("gdrive-local-config-path"); localConfigPath == "" {
|
|
|
|
panic("local-config-path not set.")
|
|
|
|
} else if basedir := c.String("basedir"); basedir == "" {
|
|
|
|
panic("basedir not set.")
|
2019-03-18 20:52:38 +01:00
|
|
|
} else if storage, err := server.NewGDriveStorage(clientJsonFilepath, localConfigPath, basedir, chunkSize, logger); err != nil {
|
2018-06-19 15:30:26 +02:00
|
|
|
panic(err)
|
|
|
|
} else {
|
|
|
|
options = append(options, server.UseStorage(storage))
|
|
|
|
}
|
2017-03-22 18:09:21 +01:00
|
|
|
case "local":
|
|
|
|
if v := c.String("basedir"); v == "" {
|
|
|
|
panic("basedir not set.")
|
2018-10-27 00:15:55 +02:00
|
|
|
} else if storage, err := server.NewLocalStorage(v, logger); err != nil {
|
2017-03-22 18:09:21 +01:00
|
|
|
panic(err)
|
|
|
|
} else {
|
|
|
|
options = append(options, server.UseStorage(storage))
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic("Provider not set or invalid.")
|
|
|
|
}
|
|
|
|
|
|
|
|
srvr, err := server.New(
|
|
|
|
options...,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
2018-10-27 00:15:55 +02:00
|
|
|
logger.Println(color.RedString("Error starting server: %s", err.Error()))
|
2017-03-22 18:09:21 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
srvr.Run()
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Cmd{
|
|
|
|
App: app,
|
|
|
|
}
|
|
|
|
}
|