config.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. "regexp"
  7. "bufio"
  8. "strconv"
  9. "path/filepath"
  10. )
  11. const (
  12. CONFIG_DIRECTORY_DEFAULT string = "~/.config/strlstloltest/it/can/do/more/nesting/"
  13. CONFIG_FILENAME_DEFAULT string = "strlst"
  14. CONFIG_EXAMPLE string = `# this is an example configuration with a semantic placeholder in each field
  15. # lines beginning with a number sign are comments
  16. # %s is used as a (necessary) placeholder for the url
  17. url_fmt=https://%s/path/to/files/
  18. # accessible ip or domain of webserver
  19. url=somewhere.someplace
  20. # SSH information is used for file transfer purposes
  21. ssh_port=22
  22. ssh_user=strlst
  23. # path to the identity file for automatic transfer
  24. ssh_identity_path=~/.ssh/copyservice_rsa
  25. # destination directory on the remote host
  26. scp_directory=~/example/target/directory
  27. secret=examplesecrettobekeptsafe
  28. `
  29. )
  30. type Configuration struct {
  31. // specifies where to look, and what HTTP structure to insert url in
  32. url_fmt, url string
  33. // ssh information used for copy service, specifies port to use
  34. // and identity file
  35. ssh_user, ssh_identity_path, scp_directory string
  36. ssh_port int
  37. // specifies encryption secret
  38. secret string
  39. }
  40. func GetHomeDir() string {
  41. // query home directory
  42. home, err := os.UserHomeDir()
  43. if err != nil {
  44. fmt.Fprintf(os.Stderr, "fatal error: user home directory could not be determined\n")
  45. os.Exit(EXIT_HOME_INVALID)
  46. }
  47. return home
  48. }
  49. func GetConfigDefaultPath() string {
  50. return filepath.Join(GetHomeDir(), ".config", "strlst", "strlst")
  51. }
  52. func ConfigurationToString(config *Configuration, obfuscate_secret bool) string {
  53. secret := "***"
  54. if !obfuscate_secret {
  55. secret = config.secret
  56. }
  57. return fmt.Sprintf(
  58. "configuration { url_fmt = %s, url = %s, ssh_user = %s, ssh_user = %v, ssh_identity_path = %s, scp_directory = %s, secret = %s }",
  59. config.url_fmt,
  60. config.url,
  61. config.ssh_user,
  62. config.ssh_port,
  63. config.ssh_identity_path,
  64. config.scp_directory,
  65. secret,
  66. )
  67. }
  68. func GetConfiguration(program *string, path *string) Configuration {
  69. config := Configuration { ssh_port: -1 }
  70. // open file for reading
  71. configuration_file, err := os.Open(*path)
  72. // if file does not exist
  73. if os.IsNotExist(err) {
  74. fmt.Fprintf(os.Stderr, "%s: specified configuration file does not exist\n", *program)
  75. os.Exit(EXIT_SPECIFIED_PATH_INVALID)
  76. }
  77. defer configuration_file.Close()
  78. // process configuration file line for line
  79. matchers := [...](*regexp.Regexp) {
  80. regexp.MustCompile("^#.*$"),
  81. regexp.MustCompile("^url_fmt *= *([^ ].*)$"),
  82. regexp.MustCompile("^url *= *([^ ].*)$"),
  83. regexp.MustCompile("^ssh_user *= *([^ ].*)$"),
  84. regexp.MustCompile("^ssh_port *= *([0-9]+)$"),
  85. regexp.MustCompile("^ssh_identity_path *= *([^ ].*)$"),
  86. regexp.MustCompile("^scp_directory *= *([^ ].*)$"),
  87. regexp.MustCompile("^secret *= *([^ ].*)$"),
  88. }
  89. // create scanner to iterate file contents
  90. scanner := bufio.NewScanner(configuration_file)
  91. // iterate file contents
  92. for scanner.Scan() {
  93. line := scanner.Text()
  94. // match line against matchers to parse contents
  95. for index, matcher := range matchers {
  96. if matcher.MatchString(line) {
  97. // comment, skip
  98. if index == 0 { continue }
  99. // find submatch (singular) for anything that isn't a comment
  100. submatches := matchers[index].FindAllStringSubmatch(line, 1)
  101. if len(submatches) < 1 || len(submatches[0]) < 2 {
  102. fmt.Fprintf(os.Stderr, "%s: error matching at line: %s\n", *program, line)
  103. continue
  104. }
  105. submatch := submatches[0][1]
  106. // ugly solution, maybe use maps instead
  107. switch index {
  108. case 1: config.url_fmt = submatch
  109. case 2: config.url = submatch
  110. case 3: config.ssh_user = submatch
  111. case 4:
  112. value, err := strconv.Atoi(submatch)
  113. if err != nil {
  114. fmt.Fprintf(os.Stderr, "%s: error parsing port %s\n", *program, submatch)
  115. os.Exit(EXIT_CONFIG_INVALID)
  116. }
  117. config.ssh_port = value
  118. case 5: config.ssh_identity_path = submatch
  119. case 6: config.scp_directory = submatch
  120. case 7: config.secret = submatch
  121. }
  122. break
  123. }
  124. }
  125. }
  126. return config
  127. }
  128. func IsConfigurationValid(config *Configuration) bool {
  129. // very basic validation
  130. return strings.Contains(config.url_fmt, "http") &&
  131. strings.Contains(config.url, ".") &&
  132. config.ssh_user != "" &&
  133. config.ssh_port > 0 &&
  134. strings.Contains(config.ssh_identity_path, "/") &&
  135. strings.Contains(config.scp_directory, "/") &&
  136. config.secret != ""
  137. }