選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

cmd.go 11 KiB

4年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
5年前
3年前
5年前
3年前
5年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
5年前
3年前
5年前
3年前
5年前
3年前
5年前
5年前
3年前
3年前
5年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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.2.1"
  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. EnvVar: "LISTENER",
  34. },
  35. // redirect to https?
  36. // hostnames
  37. cli.StringFlag{
  38. Name: "profile-listener",
  39. Usage: "127.0.0.1:6060",
  40. Value: "",
  41. EnvVar: "PROFILE_LISTENER",
  42. },
  43. cli.BoolFlag{
  44. Name: "force-https",
  45. Usage: "",
  46. EnvVar: "FORCE_HTTPS",
  47. },
  48. cli.StringFlag{
  49. Name: "tls-listener",
  50. Usage: "127.0.0.1:8443",
  51. Value: "",
  52. EnvVar: "TLS_LISTENER",
  53. },
  54. cli.BoolFlag{
  55. Name: "tls-listener-only",
  56. Usage: "",
  57. EnvVar: "TLS_LISTENER_ONLY",
  58. },
  59. cli.StringFlag{
  60. Name: "tls-cert-file",
  61. Value: "",
  62. EnvVar: "TLS_CERT_FILE",
  63. },
  64. cli.StringFlag{
  65. Name: "tls-private-key",
  66. Value: "",
  67. EnvVar: "TLS_PRIVATE_KEY",
  68. },
  69. cli.StringFlag{
  70. Name: "temp-path",
  71. Usage: "path to temp files",
  72. Value: os.TempDir(),
  73. EnvVar: "TEMP_PATH",
  74. },
  75. cli.StringFlag{
  76. Name: "web-path",
  77. Usage: "path to static web files",
  78. Value: "",
  79. EnvVar: "WEB_PATH",
  80. },
  81. cli.StringFlag{
  82. Name: "proxy-path",
  83. Usage: "path prefix when service is run behind a proxy",
  84. Value: "",
  85. EnvVar: "PROXY_PATH",
  86. },
  87. cli.StringFlag{
  88. Name: "proxy-port",
  89. Usage: "port of the proxy when the service is run behind a proxy",
  90. Value: "",
  91. EnvVar: "PROXY_PORT",
  92. },
  93. cli.StringFlag{
  94. Name: "ga-key",
  95. Usage: "key for google analytics (front end)",
  96. Value: "",
  97. EnvVar: "GA_KEY",
  98. },
  99. cli.StringFlag{
  100. Name: "uservoice-key",
  101. Usage: "key for user voice (front end)",
  102. Value: "",
  103. EnvVar: "USERVOICE_KEY",
  104. },
  105. cli.StringFlag{
  106. Name: "provider",
  107. Usage: "s3|gdrive|local",
  108. Value: "",
  109. EnvVar: "PROVIDER",
  110. },
  111. cli.StringFlag{
  112. Name: "s3-endpoint",
  113. Usage: "",
  114. Value: "",
  115. EnvVar: "S3_ENDPOINT",
  116. },
  117. cli.StringFlag{
  118. Name: "s3-region",
  119. Usage: "",
  120. Value: "eu-west-1",
  121. EnvVar: "S3_REGION",
  122. },
  123. cli.StringFlag{
  124. Name: "aws-access-key",
  125. Usage: "",
  126. Value: "",
  127. EnvVar: "AWS_ACCESS_KEY",
  128. },
  129. cli.StringFlag{
  130. Name: "aws-secret-key",
  131. Usage: "",
  132. Value: "",
  133. EnvVar: "AWS_SECRET_KEY",
  134. },
  135. cli.StringFlag{
  136. Name: "bucket",
  137. Usage: "",
  138. Value: "",
  139. EnvVar: "BUCKET",
  140. },
  141. cli.BoolFlag{
  142. Name: "s3-no-multipart",
  143. Usage: "Disables S3 Multipart Puts",
  144. EnvVar: "S3_NO_MULTIPART",
  145. },
  146. cli.BoolFlag{
  147. Name: "s3-path-style",
  148. Usage: "Forces path style URLs, required for Minio.",
  149. EnvVar: "S3_PATH_STYLE",
  150. },
  151. cli.StringFlag{
  152. Name: "gdrive-client-json-filepath",
  153. Usage: "",
  154. Value: "",
  155. EnvVar: "GDRIVE_CLIENT_JSON_FILEPATH",
  156. },
  157. cli.StringFlag{
  158. Name: "gdrive-local-config-path",
  159. Usage: "",
  160. Value: "",
  161. EnvVar: "GDRIVE_LOCAL_CONFIG_PATH",
  162. },
  163. cli.IntFlag{
  164. Name: "gdrive-chunk-size",
  165. Usage: "",
  166. Value: googleapi.DefaultUploadChunkSize / 1024 / 1024,
  167. EnvVar: "GDRIVE_CHUNK_SIZE",
  168. },
  169. cli.StringFlag{
  170. Name: "storj-access",
  171. Usage: "Access for the project",
  172. Value: "",
  173. EnvVar: "STORJ_ACCESS",
  174. },
  175. cli.StringFlag{
  176. Name: "storj-bucket",
  177. Usage: "Bucket to use within the project",
  178. Value: "",
  179. EnvVar: "STORJ_BUCKET",
  180. },
  181. cli.IntFlag{
  182. Name: "rate-limit",
  183. Usage: "requests per minute",
  184. Value: 0,
  185. EnvVar: "RATE_LIMIT",
  186. },
  187. cli.IntFlag{
  188. Name: "purge-days",
  189. Usage: "number of days after uploads are purged automatically",
  190. Value: 0,
  191. EnvVar: "PURGE_DAYS",
  192. },
  193. cli.IntFlag{
  194. Name: "purge-interval",
  195. Usage: "interval in hours to run the automatic purge for",
  196. Value: 0,
  197. EnvVar: "PURGE_INTERVAL",
  198. },
  199. cli.Int64Flag{
  200. Name: "max-upload-size",
  201. Usage: "max limit for upload, in kilobytes",
  202. Value: 0,
  203. EnvVar: "MAX_UPLOAD_SIZE",
  204. },
  205. cli.StringFlag{
  206. Name: "lets-encrypt-hosts",
  207. Usage: "host1, host2",
  208. Value: "",
  209. EnvVar: "HOSTS",
  210. },
  211. cli.StringFlag{
  212. Name: "log",
  213. Usage: "/var/log/transfersh.log",
  214. Value: "",
  215. EnvVar: "LOG",
  216. },
  217. cli.StringFlag{
  218. Name: "basedir",
  219. Usage: "path to storage",
  220. Value: "",
  221. EnvVar: "BASEDIR",
  222. },
  223. cli.StringFlag{
  224. Name: "clamav-host",
  225. Usage: "clamav-host",
  226. Value: "",
  227. EnvVar: "CLAMAV_HOST",
  228. },
  229. cli.StringFlag{
  230. Name: "virustotal-key",
  231. Usage: "virustotal-key",
  232. Value: "",
  233. EnvVar: "VIRUSTOTAL_KEY",
  234. },
  235. cli.BoolFlag{
  236. Name: "profiler",
  237. Usage: "enable profiling",
  238. EnvVar: "PROFILER",
  239. },
  240. cli.StringFlag{
  241. Name: "http-auth-user",
  242. Usage: "user for http basic auth",
  243. Value: "",
  244. EnvVar: "HTTP_AUTH_USER",
  245. },
  246. cli.StringFlag{
  247. Name: "http-auth-pass",
  248. Usage: "pass for http basic auth",
  249. Value: "",
  250. EnvVar: "HTTP_AUTH_PASS",
  251. },
  252. cli.StringFlag{
  253. Name: "ip-whitelist",
  254. Usage: "comma separated list of ips allowed to connect to the service",
  255. Value: "",
  256. EnvVar: "IP_WHITELIST",
  257. },
  258. cli.StringFlag{
  259. Name: "ip-blacklist",
  260. Usage: "comma separated list of ips not allowed to connect to the service",
  261. Value: "",
  262. EnvVar: "IP_BLACKLIST",
  263. },
  264. cli.StringFlag{
  265. Name: "cors-domains",
  266. Usage: "comma separated list of domains allowed for CORS requests",
  267. Value: "",
  268. EnvVar: "CORS_DOMAINS",
  269. },
  270. }
  271. type Cmd struct {
  272. *cli.App
  273. }
  274. func VersionAction(c *cli.Context) {
  275. fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh %s: Easy file sharing from the command line", Version)))
  276. }
  277. func New() *Cmd {
  278. logger := log.New(os.Stdout, "[transfer.sh]", log.LstdFlags)
  279. app := cli.NewApp()
  280. app.Name = "transfer.sh"
  281. app.Author = ""
  282. app.Usage = "transfer.sh"
  283. app.Description = `Easy file sharing from the command line`
  284. app.Version = Version
  285. app.Flags = globalFlags
  286. app.CustomAppHelpTemplate = helpTemplate
  287. app.Commands = []cli.Command{
  288. {
  289. Name: "version",
  290. Action: VersionAction,
  291. },
  292. }
  293. app.Before = func(c *cli.Context) error {
  294. return nil
  295. }
  296. app.Action = func(c *cli.Context) {
  297. options := []server.OptionFn{}
  298. if v := c.String("listener"); v != "" {
  299. options = append(options, server.Listener(v))
  300. }
  301. if v := c.String("cors-domains"); v != "" {
  302. options = append(options, server.CorsDomains(v))
  303. }
  304. if v := c.String("tls-listener"); v == "" {
  305. } else if c.Bool("tls-listener-only") {
  306. options = append(options, server.TLSListener(v, true))
  307. } else {
  308. options = append(options, server.TLSListener(v, false))
  309. }
  310. if v := c.String("profile-listener"); v != "" {
  311. options = append(options, server.ProfileListener(v))
  312. }
  313. if v := c.String("web-path"); v != "" {
  314. options = append(options, server.WebPath(v))
  315. }
  316. if v := c.String("proxy-path"); v != "" {
  317. options = append(options, server.ProxyPath(v))
  318. }
  319. if v := c.String("proxy-port"); v != "" {
  320. options = append(options, server.ProxyPort(v))
  321. }
  322. if v := c.String("ga-key"); v != "" {
  323. options = append(options, server.GoogleAnalytics(v))
  324. }
  325. if v := c.String("uservoice-key"); v != "" {
  326. options = append(options, server.UserVoice(v))
  327. }
  328. if v := c.String("temp-path"); v != "" {
  329. options = append(options, server.TempPath(v))
  330. }
  331. if v := c.String("log"); v != "" {
  332. options = append(options, server.LogFile(logger, v))
  333. } else {
  334. options = append(options, server.Logger(logger))
  335. }
  336. if v := c.String("lets-encrypt-hosts"); v != "" {
  337. options = append(options, server.UseLetsEncrypt(strings.Split(v, ",")))
  338. }
  339. if v := c.String("virustotal-key"); v != "" {
  340. options = append(options, server.VirustotalKey(v))
  341. }
  342. if v := c.String("clamav-host"); v != "" {
  343. options = append(options, server.ClamavHost(v))
  344. }
  345. if v := c.Int64("max-upload-size"); v > 0 {
  346. options = append(options, server.MaxUploadSize(v))
  347. }
  348. if v := c.Int("rate-limit"); v > 0 {
  349. options = append(options, server.RateLimit(v))
  350. }
  351. purgeDays := c.Int("purge-days")
  352. purgeInterval := c.Int("purge-interval")
  353. if purgeDays > 0 && purgeInterval > 0 {
  354. options = append(options, server.Purge(purgeDays, purgeInterval))
  355. }
  356. if cert := c.String("tls-cert-file"); cert == "" {
  357. } else if pk := c.String("tls-private-key"); pk == "" {
  358. } else {
  359. options = append(options, server.TLSConfig(cert, pk))
  360. }
  361. if c.Bool("profiler") {
  362. options = append(options, server.EnableProfiler())
  363. }
  364. if c.Bool("force-https") {
  365. options = append(options, server.ForceHTTPs())
  366. }
  367. if httpAuthUser := c.String("http-auth-user"); httpAuthUser == "" {
  368. } else if httpAuthPass := c.String("http-auth-pass"); httpAuthPass == "" {
  369. } else {
  370. options = append(options, server.HttpAuthCredentials(httpAuthUser, httpAuthPass))
  371. }
  372. applyIPFilter := false
  373. ipFilterOptions := server.IPFilterOptions{}
  374. if ipWhitelist := c.String("ip-whitelist"); ipWhitelist != "" {
  375. applyIPFilter = true
  376. ipFilterOptions.AllowedIPs = strings.Split(ipWhitelist, ",")
  377. ipFilterOptions.BlockByDefault = true
  378. }
  379. if ipBlacklist := c.String("ip-blacklist"); ipBlacklist != "" {
  380. applyIPFilter = true
  381. ipFilterOptions.BlockedIPs = strings.Split(ipBlacklist, ",")
  382. }
  383. if applyIPFilter {
  384. options = append(options, server.FilterOptions(ipFilterOptions))
  385. }
  386. switch provider := c.String("provider"); provider {
  387. case "s3":
  388. if accessKey := c.String("aws-access-key"); accessKey == "" {
  389. panic("access-key not set.")
  390. } else if secretKey := c.String("aws-secret-key"); secretKey == "" {
  391. panic("secret-key not set.")
  392. } else if bucket := c.String("bucket"); bucket == "" {
  393. panic("bucket not set.")
  394. } else if storage, err := server.NewS3Storage(accessKey, secretKey, bucket, purgeDays, c.String("s3-region"), c.String("s3-endpoint"), c.Bool("s3-no-multipart"), c.Bool("s3-path-style"), logger); err != nil {
  395. panic(err)
  396. } else {
  397. options = append(options, server.UseStorage(storage))
  398. }
  399. case "gdrive":
  400. chunkSize := c.Int("gdrive-chunk-size")
  401. if clientJsonFilepath := c.String("gdrive-client-json-filepath"); clientJsonFilepath == "" {
  402. panic("client-json-filepath not set.")
  403. } else if localConfigPath := c.String("gdrive-local-config-path"); localConfigPath == "" {
  404. panic("local-config-path not set.")
  405. } else if basedir := c.String("basedir"); basedir == "" {
  406. panic("basedir not set.")
  407. } else if storage, err := server.NewGDriveStorage(clientJsonFilepath, localConfigPath, basedir, chunkSize, logger); err != nil {
  408. panic(err)
  409. } else {
  410. options = append(options, server.UseStorage(storage))
  411. }
  412. case "storj":
  413. if access := c.String("storj-access"); access == "" {
  414. panic("storj-access not set.")
  415. } else if bucket := c.String("storj-bucket"); bucket == "" {
  416. panic("storj-bucket not set.")
  417. } else if storage, err := server.NewStorjStorage(access, bucket, purgeDays, logger); err != nil {
  418. panic(err)
  419. } else {
  420. options = append(options, server.UseStorage(storage))
  421. }
  422. case "local":
  423. if v := c.String("basedir"); v == "" {
  424. panic("basedir not set.")
  425. } else if storage, err := server.NewLocalStorage(v, logger); err != nil {
  426. panic(err)
  427. } else {
  428. options = append(options, server.UseStorage(storage))
  429. }
  430. default:
  431. panic("Provider not set or invalid.")
  432. }
  433. srvr, err := server.New(
  434. options...,
  435. )
  436. if err != nil {
  437. logger.Println(color.RedString("Error starting server: %s", err.Error()))
  438. return
  439. }
  440. srvr.Run()
  441. }
  442. return &Cmd{
  443. App: app,
  444. }
  445. }