190 lines
4.2 KiB
Go
190 lines
4.2 KiB
Go
![]() |
package config
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
|
||
|
"github.com/rs/zerolog"
|
||
|
"github.com/spf13/viper"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
version = "0.2"
|
||
|
title = "HellPot"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
// BindAddr is defined via our toml configuration file. It is the address that HellPot listens on.
|
||
|
BindAddr string
|
||
|
// BindPort is defined via our toml configuration file. It is the port that HellPot listens on.
|
||
|
BindPort string
|
||
|
// Paths are defined via our toml configuration file. These are the paths that HellPot will present for "robots.txt"
|
||
|
// These are also the paths that HellPot will respond for. Other paths will throw a warning and will serve a 404.
|
||
|
Paths []string
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
// Filename returns the current location of our toml config file.
|
||
|
Filename string
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
f *os.File
|
||
|
err error
|
||
|
|
||
|
customconfig = false
|
||
|
home string
|
||
|
configLocations []string
|
||
|
)
|
||
|
|
||
|
/*
|
||
|
Opt represents our program options.
|
||
|
nitially the values that are defined in Opt will be used to define details.
|
||
|
Beyond that, default values will be replaced by options from our config file.
|
||
|
*/
|
||
|
var Opt map[string]map[string]interface{}
|
||
|
|
||
|
var (
|
||
|
// Debug is our global debug toggle
|
||
|
Debug bool
|
||
|
|
||
|
prefConfigLocation string
|
||
|
snek *viper.Viper
|
||
|
)
|
||
|
|
||
|
func init() {
|
||
|
if home, err = os.UserHomeDir(); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
prefConfigLocation = home + "/.config/" + title
|
||
|
Opt = make(map[string]map[string]interface{})
|
||
|
snek = viper.New()
|
||
|
}
|
||
|
|
||
|
// Init will initialize our toml configuration engine and define our default configuration values which can be written to a new configuration file if desired
|
||
|
func Init() {
|
||
|
snek.SetConfigType("toml")
|
||
|
snek.SetConfigName("config")
|
||
|
|
||
|
argParse()
|
||
|
|
||
|
if customconfig {
|
||
|
associate()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
acquireClue()
|
||
|
|
||
|
setDefaults()
|
||
|
|
||
|
for _, loc := range configLocations {
|
||
|
snek.AddConfigPath(loc)
|
||
|
}
|
||
|
|
||
|
if err = snek.MergeInConfig(); err != nil {
|
||
|
if _, err := os.Stat(prefConfigLocation); os.IsNotExist(err) {
|
||
|
if err = os.Mkdir(prefConfigLocation, 0755); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}
|
||
|
if err = snek.SafeWriteConfigAs(prefConfigLocation + "/" + "config.toml"); err != nil {
|
||
|
fmt.Println(err.Error())
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Filename = snek.ConfigFileUsed()
|
||
|
|
||
|
associate()
|
||
|
}
|
||
|
|
||
|
func setDefaults() {
|
||
|
var configSections = []string{"logger", "http"}
|
||
|
|
||
|
Opt["logger"] = map[string]interface{}{
|
||
|
"debug": true,
|
||
|
"directory": home + "/.config/" + title + "/logs/",
|
||
|
}
|
||
|
Opt["data"] = map[string]interface{}{
|
||
|
"directory": home + "/.config/" + title + "./.data/",
|
||
|
"maxsizeobj": 20,
|
||
|
}
|
||
|
Opt["http"] = map[string]interface{}{
|
||
|
"bind_addr": "127.0.0.1",
|
||
|
"bind_port": "8080",
|
||
|
"paths": []string{
|
||
|
"wp-login.php",
|
||
|
"wp-login",
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, def := range configSections {
|
||
|
snek.SetDefault(def, Opt[def])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func acquireClue() {
|
||
|
configLocations = append(configLocations, prefConfigLocation)
|
||
|
configLocations = append(configLocations, "/etc/"+title+"/")
|
||
|
configLocations = append(configLocations, "./")
|
||
|
configLocations = append(configLocations, "../")
|
||
|
}
|
||
|
|
||
|
func loadCustomConfig(path string) {
|
||
|
if f, err = os.Open(path); err != nil {
|
||
|
println("Error opening specified config file: " + path)
|
||
|
panic("config file open fatal error: " + err.Error())
|
||
|
}
|
||
|
buf, err := ioutil.ReadAll(f)
|
||
|
err2 := snek.ReadConfig(bytes.NewBuffer(buf))
|
||
|
switch {
|
||
|
case err != nil:
|
||
|
fmt.Println("config file read fatal error: ", err.Error())
|
||
|
case err2 != nil:
|
||
|
fmt.Println("config file read fatal error: ", err2.Error())
|
||
|
default:
|
||
|
break
|
||
|
}
|
||
|
customconfig = true
|
||
|
}
|
||
|
|
||
|
// TODO: should probably just make a proper CLI with flags or something
|
||
|
func argParse() {
|
||
|
for i, arg := range os.Args {
|
||
|
switch arg {
|
||
|
case "-c":
|
||
|
if len(os.Args) <= i-1 {
|
||
|
panic("syntax error! expected file after -c")
|
||
|
}
|
||
|
loadCustomConfig(os.Args[i+1])
|
||
|
default:
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func associate() {
|
||
|
var newOpt map[string]map[string]interface{}
|
||
|
newOpt = Opt
|
||
|
for category, opt := range Opt {
|
||
|
for optname, value := range opt {
|
||
|
if snek.IsSet(category + "." + optname) {
|
||
|
newOpt[category][optname] = value
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Opt = newOpt
|
||
|
Debug = snek.GetBool("logger.debug")
|
||
|
logDir = snek.GetString("logger.directory")
|
||
|
BindAddr = snek.GetString("http.bind_addr")
|
||
|
BindPort = snek.GetString("http.bind_port")
|
||
|
Paths = snek.GetStringSlice("http.paths")
|
||
|
|
||
|
if Debug {
|
||
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||
|
}
|
||
|
}
|