config-core.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. //
  2. // Copyright (C) 2017-2018 Marcus Rohrmoser, http://purl.mro.name/ShaarliGo
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. //
  17. package main
  18. import (
  19. "crypto/rand"
  20. "encoding/base64"
  21. "fmt"
  22. "io"
  23. "io/ioutil"
  24. "os"
  25. "path/filepath"
  26. "gopkg.in/yaml.v2"
  27. )
  28. var configFileName string
  29. func init() {
  30. configFileName = filepath.Join(dirApp, "config.yaml")
  31. }
  32. type RegexpReplaceAllString struct {
  33. Regexp string `yaml:"regexp"`
  34. ReplaceAllString string `yaml:"replace_all_string"`
  35. }
  36. type Config struct {
  37. Title string `yaml:"title"` // title for cheap non-feed screens (login, tools, etc)
  38. Uid string `yaml:"uid"` // for login
  39. PwdBcrypt string `yaml:"pwd_bcrypt"`
  40. CookieStoreSecret string `yaml:"cookie_secret"`
  41. TimeZone string `yaml:"timezone"`
  42. Skin string `yaml:"skin"`
  43. LinksPerPage int `yaml:"links_per_page"` // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L18
  44. BanAfter int `yaml:"ban_after"` // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L20
  45. BanSeconds int `yaml:"ban_seconds"` // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L21
  46. UrlCleaner []RegexpReplaceAllString `yaml:"url_cleaner"`
  47. // Redirector string `yaml:"redirector"` // actually a prefix to href - Hardcoded in xslt
  48. }
  49. func LoadConfig() (Config, error) {
  50. // seed the cookie store secret
  51. buf := make([]byte, 32)
  52. if _, err := io.ReadFull(rand.Reader, buf); err != nil {
  53. return Config{}, err
  54. }
  55. ret := Config{
  56. CookieStoreSecret: base64.StdEncoding.EncodeToString(buf),
  57. TimeZone: "Europe/Paris",
  58. Skin: "default/de",
  59. LinksPerPage: 100, // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L18
  60. BanAfter: 4, // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L20
  61. BanSeconds: 14400, // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L21
  62. UrlCleaner: []RegexpReplaceAllString{
  63. {Regexp: "[\\?&]utm_source=.*$", ReplaceAllString: ""}, // We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...)
  64. {Regexp: "#xtor=RSS-.*$", ReplaceAllString: ""},
  65. {Regexp: "^(?i)(?:https?://)?(?:(?:www|m)\\.)?heise\\.de/.*?(-\\d+)(?:\\.html)?(?:[\\?#].*)?$", ReplaceAllString: "https://heise.de/${1}"},
  66. {Regexp: "^(?i)(?:https?://)?(?:(?:www|m)\\.)?spiegel\\.de/.*?-(\\d+)(?:\\.html.*)?", ReplaceAllString: "https://spiegel.de/article.do?id=${1}"},
  67. {Regexp: "^(?i)(?:https?://)?(?:(?:www|m)\\.)?sueddeutsche\\.de/.*?-(\\d+\\.\\d+)(?:\\.html.*)?$", ReplaceAllString: "https://sz.de/${1}"},
  68. {Regexp: "^(?i)(?:https?://)?(?:(?:www|m)\\.)?youtube.com/watch\\?v=([^&]+)(?:.*&(t=[^&]+))?(?:.*)$", ReplaceAllString: "https://youtu.be/${1}?${2}"},
  69. },
  70. // Redirector: "http://anonym.to/?",
  71. }
  72. if read, err := ioutil.ReadFile(configFileName); err == nil {
  73. err = yaml.Unmarshal(read, &ret)
  74. if ret.LinksPerPage < 1 {
  75. ret.LinksPerPage = 1
  76. }
  77. return ret, err
  78. } else if os.IsNotExist(err) {
  79. return ret, nil
  80. } else {
  81. return ret, err
  82. }
  83. }
  84. func (cfg Config) Save() error {
  85. if out, err := yaml.Marshal(cfg); err == nil {
  86. tmpFileName := fmt.Sprintf("%s~%d", configFileName, os.Getpid())
  87. if err = os.MkdirAll(filepath.Dir(configFileName), 0770); err == nil {
  88. if err = ioutil.WriteFile(tmpFileName, out, 0660); err == nil {
  89. err = os.Rename(tmpFileName, configFileName)
  90. }
  91. }
  92. return err
  93. } else {
  94. return err
  95. }
  96. }
  97. func (cfg Config) IsConfigured() bool {
  98. return cfg.PwdBcrypt != ""
  99. }