command.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright (C) 2019-2022 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package command
  15. import (
  16. "fmt"
  17. "os"
  18. "strings"
  19. "time"
  20. )
  21. const (
  22. minTimeout = 1
  23. maxTimeout = 300
  24. defaultTimeout = 30
  25. )
  26. var (
  27. config Config
  28. )
  29. // Command define the configuration for a specific commands
  30. type Command struct {
  31. // Path is the command path as defined in the hook configuration
  32. Path string `json:"path" mapstructure:"path"`
  33. // Timeout specifies a time limit, in seconds, for the command execution.
  34. // This value overrides the global timeout if set.
  35. // Do not use variables with the SFTPGO_ prefix to avoid conflicts with env
  36. // vars that SFTPGo sets
  37. Timeout int `json:"timeout" mapstructure:"timeout"`
  38. // Env defines additional environment variable for the commands.
  39. // Each entry is of the form "key=value".
  40. // These values are added to the global environment variables if any
  41. Env []string `json:"env" mapstructure:"env"`
  42. }
  43. // Config defines the configuration for external commands such as
  44. // program based hooks
  45. type Config struct {
  46. // Timeout specifies a global time limit, in seconds, for the external commands execution
  47. Timeout int `json:"timeout" mapstructure:"timeout"`
  48. // Env defines additional environment variable for the commands.
  49. // Each entry is of the form "key=value".
  50. // Do not use variables with the SFTPGO_ prefix to avoid conflicts with env
  51. // vars that SFTPGo sets
  52. Env []string `json:"env" mapstructure:"env"`
  53. // Commands defines configuration for specific commands
  54. Commands []Command `json:"commands" mapstructure:"commands"`
  55. }
  56. func init() {
  57. config = Config{
  58. Timeout: defaultTimeout,
  59. }
  60. }
  61. // Initialize configures commands
  62. func (c Config) Initialize() error {
  63. if c.Timeout < minTimeout || c.Timeout > maxTimeout {
  64. return fmt.Errorf("invalid timeout %v", c.Timeout)
  65. }
  66. for _, env := range c.Env {
  67. if len(strings.Split(env, "=")) != 2 {
  68. return fmt.Errorf("invalid env var %#v", env)
  69. }
  70. }
  71. for idx, cmd := range c.Commands {
  72. if cmd.Path == "" {
  73. return fmt.Errorf("invalid path %#v", cmd.Path)
  74. }
  75. if cmd.Timeout == 0 {
  76. c.Commands[idx].Timeout = c.Timeout
  77. } else {
  78. if cmd.Timeout < minTimeout || cmd.Timeout > maxTimeout {
  79. return fmt.Errorf("invalid timeout %v for command %#v", cmd.Timeout, cmd.Path)
  80. }
  81. }
  82. for _, env := range cmd.Env {
  83. if len(strings.Split(env, "=")) != 2 {
  84. return fmt.Errorf("invalid env var %#v for command %#v", env, cmd.Path)
  85. }
  86. }
  87. }
  88. config = c
  89. return nil
  90. }
  91. // GetConfig returns the configuration for the specified command
  92. func GetConfig(command string) (time.Duration, []string) {
  93. env := os.Environ()
  94. timeout := time.Duration(config.Timeout) * time.Second
  95. env = append(env, config.Env...)
  96. for _, cmd := range config.Commands {
  97. if cmd.Path == command {
  98. timeout = time.Duration(cmd.Timeout) * time.Second
  99. env = append(env, cmd.Env...)
  100. break
  101. }
  102. }
  103. return timeout, env
  104. }