You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-sendxmpp/parseconfig.go

158 lines
4.0 KiB
Go

// Copyright Martin Dosch.
// Use of this source code is governed by the BSD-2-clause
// license that can be found in the LICENSE file.
2 years ago
package main
import (
"bufio"
"fmt"
2 years ago
"log"
"os"
"os/exec"
"os/user"
"runtime"
"strconv"
"strings"
)
func findConfig() (string, error) {
// Get the current user.
curUser, err := user.Current()
if err != nil {
return "", fmt.Errorf("findConfig: failed to get current user: %w", err)
2 years ago
}
// Get home directory.
home := curUser.HomeDir
if home == "" {
return "", fmt.Errorf("findConfig: no home directory found")
2 years ago
}
osConfigDir := os.Getenv("$XDG_CONFIG_HOME")
if osConfigDir == "" {
osConfigDir = home + "/.config"
}
12 months ago
configFiles := [3]string{
osConfigDir + "/go-sendxmpp/config",
2 years ago
osConfigDir + "/go-sendxmpp/sendxmpprc", home +
12 months ago
"/.sendxmpprc",
}
2 years ago
for _, r := range configFiles {
// Check that the config file is existing.
_, err := os.Stat(r)
if err == nil {
2 years ago
return r, nil
}
}
return "", fmt.Errorf("findConfig: no configuration file found")
2 years ago
}
// Opens the config file and returns the specified values
// for username, server and port.
func parseConfig(configPath string) (configuration, error) {
var (
output configuration
err error
)
// Use $XDG_CONFIG_HOME/.config/go-sendxmpp/config,
// $XDG_CONFIG_HOME/.config/go-sendxmpp/sendxmpprc or
// ~/.sendxmpprc if no config path is specified.
// Get systems user config path.
if configPath == "" {
configPath, err = findConfig()
if err != nil {
2 years ago
log.Fatal(err)
}
}
// Only check file permissions if we are not running on windows.
if runtime.GOOS != "windows" {
info, err := os.Stat(configPath)
if err != nil {
2 years ago
log.Fatal(err)
}
// Check for file permissions. Must be 600, 640, 440 or 400.
perm := info.Mode().Perm()
permissions := strconv.FormatInt(int64(perm), 8)
if permissions != "600" && permissions != "640" && permissions != "440" && permissions != "400" {
return output, fmt.Errorf("parseConfig: wrong permissions for %s: %s instead of 400, 440, 600 or 640.", configPath, permissions)
2 years ago
}
}
// Open config file.
file, err := os.Open(configPath)
if err != nil {
return output, fmt.Errorf("parseConfig: failed to open config file: %w", err)
2 years ago
}
defer file.Close()
2 years ago
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
// Read config file per line.
for scanner.Scan() {
if strings.HasPrefix(scanner.Text(), "#") {
continue
}
row := strings.SplitN(scanner.Text(), " ", defaultConfigRowSep)
2 years ago
switch row[0] {
case "username:":
output.username = row[1]
case "jserver:":
output.jserver = row[1]
case "password:":
output.password = row[1]
case "eval_password:":
shell := os.Getenv("SHELL")
if shell == "" {
shell = "/bin/sh"
}
out, err := exec.Command(shell, "-c", row[1]).Output()
if err != nil {
2 years ago
log.Fatal(err)
}
output.password = string(out)
if output.password[len(output.password)-1] == '\n' {
output.password = output.password[:len(output.password)-1]
}
case "port:":
output.port = row[1]
case "alias:":
output.alias = row[1]
2 years ago
default:
if len(row) >= defaultConfigRowSep {
2 years ago
if strings.Contains(scanner.Text(), ";") {
output.username = strings.Split(row[0], ";")[0]
output.jserver = strings.Split(row[0], ";")[1]
output.password = row[1]
} else {
output.username = strings.Split(row[0], ":")[0]
jserver := strings.Split(row[0], "@")
if len(jserver) < defaultLenServerConf {
2 years ago
log.Fatal("Couldn't parse config: ", row[0])
}
output.jserver = jserver[0]
output.password = row[1]
}
}
}
}
// Check if the username is a valid JID
output.username, err = MarshalJID(output.username)
if err != nil {
2 years ago
// Check whether only the local part was used by appending an @ and the
// server part.
output.username = output.username + "@" + output.jserver
// Check if the username is a valid JID now
output.username, err = MarshalJID(output.username)
if err != nil {
return output, fmt.Errorf("parseConfig: invalid username/JID: %s", output.username)
2 years ago
}
}
return output, err
}