2023-05-11 18:05:31 +00:00
|
|
|
// Copyright Martin Dosch.
|
2022-02-23 14:04:18 +00:00
|
|
|
// Use of this source code is governed by the BSD-2-clause
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2022-02-23 14:00:34 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"errors"
|
2022-08-06 09:52:47 +00:00
|
|
|
"fmt"
|
2022-02-23 14:00:34 +00:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"os/user"
|
|
|
|
"runtime"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
func findConfig() (string, error) {
|
|
|
|
// Get the current user.
|
|
|
|
curUser, err := user.Current()
|
2023-08-16 06:49:43 +00:00
|
|
|
if err != nil {
|
2023-06-07 20:28:01 +00:00
|
|
|
return "", fmt.Errorf("findConfig: failed to get current user: %w", err)
|
2022-02-23 14:00:34 +00:00
|
|
|
}
|
|
|
|
// Get home directory.
|
|
|
|
home := curUser.HomeDir
|
|
|
|
if home == "" {
|
|
|
|
return "", errors.New("no home directory found")
|
|
|
|
}
|
|
|
|
osConfigDir := os.Getenv("$XDG_CONFIG_HOME")
|
|
|
|
if osConfigDir == "" {
|
|
|
|
osConfigDir = home + "/.config"
|
|
|
|
}
|
2023-06-06 08:47:40 +00:00
|
|
|
configFiles := [3]string{
|
|
|
|
osConfigDir + "/go-sendxmpp/config",
|
2022-02-23 14:00:34 +00:00
|
|
|
osConfigDir + "/go-sendxmpp/sendxmpprc", home +
|
2023-06-06 08:47:40 +00:00
|
|
|
"/.sendxmpprc",
|
|
|
|
}
|
2022-02-23 14:00:34 +00:00
|
|
|
|
|
|
|
for _, r := range configFiles {
|
|
|
|
// Check that the config file is existing.
|
|
|
|
_, err := os.Stat(r)
|
2023-08-16 06:49:43 +00:00
|
|
|
if err == nil {
|
2022-02-23 14:00:34 +00:00
|
|
|
return r, nil
|
|
|
|
}
|
|
|
|
}
|
2022-04-25 19:29:14 +00:00
|
|
|
return "", errors.New("no configuration file found")
|
2022-02-23 14:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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()
|
2023-08-16 06:49:43 +00:00
|
|
|
if err != nil {
|
2022-02-23 14:00:34 +00:00
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only check file permissions if we are not running on windows.
|
|
|
|
if runtime.GOOS != "windows" {
|
|
|
|
info, err := os.Stat(configPath)
|
2023-08-16 06:49:43 +00:00
|
|
|
if err != nil {
|
2022-02-23 14:00:34 +00:00
|
|
|
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, errors.New("Wrong permissions for " + configPath + ": " +
|
|
|
|
permissions + " instead of 400, 440, 600 or 640.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open config file.
|
|
|
|
file, err := os.Open(configPath)
|
2023-08-16 06:49:43 +00:00
|
|
|
if err != nil {
|
2023-06-07 20:28:01 +00:00
|
|
|
return output, fmt.Errorf("parseConfig: failed to open config file: %w", err)
|
2022-02-23 14:00:34 +00:00
|
|
|
}
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
|
|
scanner.Split(bufio.ScanLines)
|
|
|
|
|
|
|
|
// Read config file per line.
|
|
|
|
for scanner.Scan() {
|
|
|
|
if strings.HasPrefix(scanner.Text(), "#") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-06-06 08:47:41 +00:00
|
|
|
row := strings.SplitN(scanner.Text(), " ", defaultConfigRowSep)
|
2022-02-23 14:00:34 +00:00
|
|
|
|
|
|
|
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()
|
2023-08-16 06:49:43 +00:00
|
|
|
if err != nil {
|
2022-02-23 14:00:34 +00:00
|
|
|
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]
|
2022-08-06 09:52:47 +00:00
|
|
|
case "alias:":
|
|
|
|
output.alias = row[1]
|
2022-02-23 14:00:34 +00:00
|
|
|
default:
|
2023-06-06 08:47:41 +00:00
|
|
|
if len(row) >= defaultConfigRowSep {
|
2022-02-23 14:00:34 +00:00
|
|
|
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], "@")
|
2023-06-06 08:47:41 +00:00
|
|
|
if len(jserver) < defaultLenServerConf {
|
2022-02-23 14:00:34 +00:00
|
|
|
log.Fatal("Couldn't parse config: ", row[0])
|
|
|
|
}
|
|
|
|
output.jserver = jserver[0]
|
|
|
|
output.password = row[1]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-06-04 13:18:50 +00:00
|
|
|
err = file.Close()
|
2023-08-16 06:49:43 +00:00
|
|
|
if err != nil {
|
2023-06-04 13:18:50 +00:00
|
|
|
fmt.Println("error closing file:", err)
|
|
|
|
}
|
2022-02-23 14:00:34 +00:00
|
|
|
|
|
|
|
// Check if the username is a valid JID
|
|
|
|
output.username, err = MarshalJID(output.username)
|
2023-08-16 06:49:43 +00:00
|
|
|
if err != nil {
|
2022-02-23 14:00:34 +00:00
|
|
|
// 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)
|
2023-08-16 06:49:43 +00:00
|
|
|
if err != nil {
|
2022-02-23 14:00:34 +00:00
|
|
|
return output, errors.New("invalid username/JID: " + output.username)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output, err
|
|
|
|
}
|