You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

431 rivejä
9.9 KiB

  1. package cmd
  2. import (
  3. "fmt"
  4. "log"
  5. "os"
  6. "strings"
  7. "github.com/dutchcoders/transfer.sh/server"
  8. "github.com/fatih/color"
  9. "github.com/urfave/cli"
  10. "google.golang.org/api/googleapi"
  11. )
  12. var Version = "1.1.2"
  13. var helpTemplate = `NAME:
  14. {{.Name}} - {{.Usage}}
  15. DESCRIPTION:
  16. {{.Description}}
  17. USAGE:
  18. {{.Name}} {{if .Flags}}[flags] {{end}}command{{if .Flags}}{{end}} [arguments...]
  19. COMMANDS:
  20. {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
  21. {{end}}{{if .Flags}}
  22. FLAGS:
  23. {{range .Flags}}{{.}}
  24. {{end}}{{end}}
  25. VERSION:
  26. ` + Version +
  27. `{{ "\n"}}`
  28. var globalFlags = []cli.Flag{
  29. cli.StringFlag{
  30. Name: "listener",
  31. Usage: "127.0.0.1:8080",
  32. Value: "127.0.0.1:8080",
  33. },
  34. // redirect to https?
  35. // hostnames
  36. cli.StringFlag{
  37. Name: "profile-listener",
  38. Usage: "127.0.0.1:6060",
  39. Value: "",
  40. },
  41. cli.BoolFlag{
  42. Name: "force-https",
  43. Usage: "",
  44. },
  45. cli.StringFlag{
  46. Name: "tls-listener",
  47. Usage: "127.0.0.1:8443",
  48. Value: "",
  49. },
  50. cli.BoolFlag{
  51. Name: "tls-listener-only",
  52. Usage: "",
  53. },
  54. cli.StringFlag{
  55. Name: "tls-cert-file",
  56. Value: "",
  57. },
  58. cli.StringFlag{
  59. Name: "tls-private-key",
  60. Value: "",
  61. },
  62. cli.StringFlag{
  63. Name: "temp-path",
  64. Usage: "path to temp files",
  65. Value: os.TempDir(),
  66. },
  67. cli.StringFlag{
  68. Name: "web-path",
  69. Usage: "path to static web files",
  70. Value: "",
  71. },
  72. cli.StringFlag{
  73. Name: "proxy-path",
  74. Usage: "path prefix when service is run behind a proxy",
  75. Value: "",
  76. },
  77. cli.StringFlag{
  78. Name: "ga-key",
  79. Usage: "key for google analytics (front end)",
  80. Value: "",
  81. },
  82. cli.StringFlag{
  83. Name: "uservoice-key",
  84. Usage: "key for user voice (front end)",
  85. Value: "",
  86. },
  87. cli.StringFlag{
  88. Name: "provider",
  89. Usage: "s3|gdrive|local",
  90. Value: "",
  91. },
  92. cli.StringFlag{
  93. Name: "s3-endpoint",
  94. Usage: "",
  95. Value: "",
  96. EnvVar: "S3_ENDPOINT",
  97. },
  98. cli.StringFlag{
  99. Name: "s3-region",
  100. Usage: "",
  101. Value: "eu-west-1",
  102. EnvVar: "S3_REGION",
  103. },
  104. cli.StringFlag{
  105. Name: "aws-access-key",
  106. Usage: "",
  107. Value: "",
  108. EnvVar: "AWS_ACCESS_KEY",
  109. },
  110. cli.StringFlag{
  111. Name: "aws-secret-key",
  112. Usage: "",
  113. Value: "",
  114. EnvVar: "AWS_SECRET_KEY",
  115. },
  116. cli.StringFlag{
  117. Name: "bucket",
  118. Usage: "",
  119. Value: "",
  120. EnvVar: "BUCKET",
  121. },
  122. cli.BoolFlag{
  123. Name: "s3-no-multipart",
  124. Usage: "Disables S3 Multipart Puts",
  125. },
  126. cli.BoolFlag{
  127. Name: "s3-path-style",
  128. Usage: "Forces path style URLs, required for Minio.",
  129. },
  130. cli.StringFlag{
  131. Name: "gdrive-client-json-filepath",
  132. Usage: "",
  133. Value: "",
  134. },
  135. cli.StringFlag{
  136. Name: "gdrive-local-config-path",
  137. Usage: "",
  138. Value: "",
  139. },
  140. cli.IntFlag{
  141. Name: "gdrive-chunk-size",
  142. Usage: "",
  143. Value: googleapi.DefaultUploadChunkSize / 1024 / 1024,
  144. },
  145. cli.StringFlag{
  146. Name: "storj-endpoint",
  147. Usage: "Satellite Address including Port.",
  148. Value: "",
  149. EnvVar: "STORJ_ENDPOINT",
  150. },
  151. cli.StringFlag{
  152. Name: "storj-apikey",
  153. Usage: "",
  154. Value: "",
  155. EnvVar: "STORJ_API_KEY",
  156. },
  157. cli.StringFlag{
  158. Name: "storj-bucket",
  159. Usage: "",
  160. Value: "",
  161. EnvVar: "STORJ_BUCKET",
  162. },
  163. cli.StringFlag{
  164. Name: "storj-enckey",
  165. Usage: "Encryption Key for local file encryption",
  166. Value: "",
  167. EnvVar: "STORJ_ENC_KEY",
  168. },
  169. cli.IntFlag{
  170. Name: "rate-limit",
  171. Usage: "requests per minute",
  172. Value: 0,
  173. EnvVar: "",
  174. },
  175. cli.StringFlag{
  176. Name: "lets-encrypt-hosts",
  177. Usage: "host1, host2",
  178. Value: "",
  179. EnvVar: "HOSTS",
  180. },
  181. cli.StringFlag{
  182. Name: "log",
  183. Usage: "/var/log/transfersh.log",
  184. Value: "",
  185. },
  186. cli.StringFlag{
  187. Name: "basedir",
  188. Usage: "path to storage",
  189. Value: "",
  190. },
  191. cli.StringFlag{
  192. Name: "clamav-host",
  193. Usage: "clamav-host",
  194. Value: "",
  195. EnvVar: "CLAMAV_HOST",
  196. },
  197. cli.StringFlag{
  198. Name: "virustotal-key",
  199. Usage: "virustotal-key",
  200. Value: "",
  201. EnvVar: "VIRUSTOTAL_KEY",
  202. },
  203. cli.BoolFlag{
  204. Name: "profiler",
  205. Usage: "enable profiling",
  206. },
  207. cli.StringFlag{
  208. Name: "http-auth-user",
  209. Usage: "user for http basic auth",
  210. Value: "",
  211. },
  212. cli.StringFlag{
  213. Name: "http-auth-pass",
  214. Usage: "pass for http basic auth",
  215. Value: "",
  216. },
  217. cli.StringFlag{
  218. Name: "ip-whitelist",
  219. Usage: "comma separated list of ips allowed to connect to the service",
  220. Value: "",
  221. },
  222. cli.StringFlag{
  223. Name: "ip-blacklist",
  224. Usage: "comma separated list of ips not allowed to connect to the service",
  225. Value: "",
  226. },
  227. }
  228. type Cmd struct {
  229. *cli.App
  230. }
  231. func VersionAction(c *cli.Context) {
  232. fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh: Easy file sharing from the command line")))
  233. }
  234. func New() *Cmd {
  235. logger := log.New(os.Stdout, "[transfer.sh]", log.LstdFlags)
  236. app := cli.NewApp()
  237. app.Name = "transfer.sh"
  238. app.Author = ""
  239. app.Usage = "transfer.sh"
  240. app.Description = `Easy file sharing from the command line`
  241. app.Version = Version
  242. app.Flags = globalFlags
  243. app.CustomAppHelpTemplate = helpTemplate
  244. app.Commands = []cli.Command{
  245. {
  246. Name: "version",
  247. Action: VersionAction,
  248. },
  249. }
  250. app.Before = func(c *cli.Context) error {
  251. return nil
  252. }
  253. app.Action = func(c *cli.Context) {
  254. options := []server.OptionFn{}
  255. if v := c.String("listener"); v != "" {
  256. options = append(options, server.Listener(v))
  257. }
  258. if v := c.String("tls-listener"); v == "" {
  259. } else if c.Bool("tls-listener-only") {
  260. options = append(options, server.TLSListener(v, true))
  261. } else {
  262. options = append(options, server.TLSListener(v, false))
  263. }
  264. if v := c.String("profile-listener"); v != "" {
  265. options = append(options, server.ProfileListener(v))
  266. }
  267. if v := c.String("web-path"); v != "" {
  268. options = append(options, server.WebPath(v))
  269. }
  270. if v := c.String("proxy-path"); v != "" {
  271. options = append(options, server.ProxyPath(v))
  272. }
  273. if v := c.String("ga-key"); v != "" {
  274. options = append(options, server.GoogleAnalytics(v))
  275. }
  276. if v := c.String("uservoice-key"); v != "" {
  277. options = append(options, server.UserVoice(v))
  278. }
  279. if v := c.String("temp-path"); v != "" {
  280. options = append(options, server.TempPath(v))
  281. }
  282. if v := c.String("log"); v != "" {
  283. options = append(options, server.LogFile(logger, v))
  284. } else {
  285. options = append(options, server.Logger(logger))
  286. }
  287. if v := c.String("lets-encrypt-hosts"); v != "" {
  288. options = append(options, server.UseLetsEncrypt(strings.Split(v, ",")))
  289. }
  290. if v := c.String("virustotal-key"); v != "" {
  291. options = append(options, server.VirustotalKey(v))
  292. }
  293. if v := c.String("clamav-host"); v != "" {
  294. options = append(options, server.ClamavHost(v))
  295. }
  296. if v := c.Int("rate-limit"); v > 0 {
  297. options = append(options, server.RateLimit(v))
  298. }
  299. if cert := c.String("tls-cert-file"); cert == "" {
  300. } else if pk := c.String("tls-private-key"); pk == "" {
  301. } else {
  302. options = append(options, server.TLSConfig(cert, pk))
  303. }
  304. if c.Bool("profiler") {
  305. options = append(options, server.EnableProfiler())
  306. }
  307. if c.Bool("force-https") {
  308. options = append(options, server.ForceHTTPs())
  309. }
  310. if httpAuthUser := c.String("http-auth-user"); httpAuthUser == "" {
  311. } else if httpAuthPass := c.String("http-auth-pass"); httpAuthPass == "" {
  312. } else {
  313. options = append(options, server.HttpAuthCredentials(httpAuthUser, httpAuthPass))
  314. }
  315. applyIPFilter := false
  316. ipFilterOptions := server.IPFilterOptions{}
  317. if ipWhitelist := c.String("ip-whitelist"); ipWhitelist != "" {
  318. applyIPFilter = true
  319. ipFilterOptions.AllowedIPs = strings.Split(ipWhitelist, ",")
  320. ipFilterOptions.BlockByDefault = true
  321. }
  322. if ipBlacklist := c.String("ip-blacklist"); ipBlacklist != "" {
  323. applyIPFilter = true
  324. ipFilterOptions.BlockedIPs = strings.Split(ipBlacklist, ",")
  325. }
  326. if applyIPFilter {
  327. options = append(options, server.FilterOptions(ipFilterOptions))
  328. }
  329. switch provider := c.String("provider"); provider {
  330. case "s3":
  331. if accessKey := c.String("aws-access-key"); accessKey == "" {
  332. panic("access-key not set.")
  333. } else if secretKey := c.String("aws-secret-key"); secretKey == "" {
  334. panic("secret-key not set.")
  335. } else if bucket := c.String("bucket"); bucket == "" {
  336. panic("bucket not set.")
  337. } else if storage, err := server.NewS3Storage(accessKey, secretKey, bucket, c.String("s3-region"), c.String("s3-endpoint"), logger, c.Bool("s3-no-multipart"), c.Bool("s3-path-style")); err != nil {
  338. panic(err)
  339. } else {
  340. options = append(options, server.UseStorage(storage))
  341. }
  342. case "gdrive":
  343. chunkSize := c.Int("gdrive-chunk-size")
  344. if clientJsonFilepath := c.String("gdrive-client-json-filepath"); clientJsonFilepath == "" {
  345. panic("client-json-filepath not set.")
  346. } else if localConfigPath := c.String("gdrive-local-config-path"); localConfigPath == "" {
  347. panic("local-config-path not set.")
  348. } else if basedir := c.String("basedir"); basedir == "" {
  349. panic("basedir not set.")
  350. } else if storage, err := server.NewGDriveStorage(clientJsonFilepath, localConfigPath, basedir, chunkSize, logger); err != nil {
  351. panic(err)
  352. } else {
  353. options = append(options, server.UseStorage(storage))
  354. }
  355. case "storj":
  356. if endpoint := c.String("storj-endpoint"); endpoint == "" {
  357. panic("storj-endpoint not set.")
  358. } else if apiKey := c.String("storj-apikey"); apiKey == "" {
  359. panic("storj-apikey not set.")
  360. } else if bucket := c.String("storj-bucket"); bucket == "" {
  361. panic("storj-enckey not set.")
  362. } else if encKey := c.String("storj-enckey"); encKey == "" {
  363. panic("storj-bucket not set.")
  364. } else if storage, err := server.NewStorjStorage(endpoint, apiKey, bucket, encKey, logger); err != nil {
  365. panic(err)
  366. } else {
  367. options = append(options, server.UseStorage(storage))
  368. }
  369. case "local":
  370. if v := c.String("basedir"); v == "" {
  371. panic("basedir not set.")
  372. } else if storage, err := server.NewLocalStorage(v, logger); err != nil {
  373. panic(err)
  374. } else {
  375. options = append(options, server.UseStorage(storage))
  376. }
  377. default:
  378. panic("Provider not set or invalid.")
  379. }
  380. srvr, err := server.New(
  381. options...,
  382. )
  383. if err != nil {
  384. logger.Println(color.RedString("Error starting server: %s", err.Error()))
  385. return
  386. }
  387. srvr.Run()
  388. }
  389. return &Cmd{
  390. App: app,
  391. }
  392. }