271 lines
9.1 KiB
Bash
Executable File
271 lines
9.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# barnard-ui
|
|
# Description: Make managing servers with barnard easy.
|
|
#
|
|
# Copyright 2019, F123 Consulting, <information@f123.org>
|
|
# Copyright 2019, Stormux, <storm_dragon@linux-a11y.org>
|
|
# Copyright 2019, Storm Dragon, <storm_dragon@linux-a11y.org>
|
|
#
|
|
# This is free software; you can redistribute it and/or modify it under the
|
|
# terms of the GNU General Public License as published by the Free
|
|
# Software Foundation; either version 3, or (at your option) any later
|
|
# version.
|
|
#
|
|
# This software is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this package; see the file COPYING. If not, write to the Free
|
|
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
# 02110-1301, USA.
|
|
#
|
|
#--code--
|
|
|
|
# the gettext essentials
|
|
export TEXTDOMAIN=barnard-ui
|
|
export TEXTDOMAINDIR=/usr/share/locale
|
|
source gettext.sh
|
|
|
|
# Log writing function
|
|
log() {
|
|
# Usage: command | log for just stdout.
|
|
# Or command |& log for stderr and stdout.
|
|
while read -r line ; do
|
|
echo "$line" | tee -a "$logFile" &> /dev/null
|
|
done
|
|
}
|
|
|
|
# Log file name is ~/.cache/scriptname.log
|
|
logFile="$HOME/.cache/${0##*/}.log"
|
|
# Clear previous logs
|
|
echo -n | tee "$logFile" &> /dev/null
|
|
|
|
# Settings to improve accessibility of dialog.
|
|
export DIALOGOPTS='--insecure --no-lines --visit-items'
|
|
|
|
inputbox() {
|
|
# Returns: text entered by the user
|
|
# Args 1, Instructions for box.
|
|
# args: 2 initial text (optional)
|
|
dialog --clear --backtitle "$(gettext "Enter text and press enter.")" \
|
|
--inputbox "$1" 0 0 "$2" --stdout
|
|
}
|
|
|
|
passwordbox() {
|
|
# Returns: text entered by the user
|
|
# Args 1, Instructions for box.
|
|
# args: 2 initial text (optional)
|
|
dialog --clear --backtitle "$(gettext "Enter text and press enter.")" \
|
|
--passwordbox "$1" 0 0 "$2" --stdout
|
|
}
|
|
|
|
msgbox() {
|
|
# Returns: None
|
|
# Shows the provided message on the screen with an ok button.
|
|
dialog --clear --msgbox "$*" 10 72
|
|
}
|
|
|
|
yesno() {
|
|
# Returns: Yes or No
|
|
# Args: Question to user.
|
|
# Called in if $(yesno) == "Yes"
|
|
# Or variable=$(yesno)
|
|
dialog --clear --backtitle "$(gettext "Press 'Enter' for \"yes\" or 'Escape' for \"no\".")" --yesno "$*" 10 80 --stdout
|
|
if [[ $? -eq 0 ]]; then
|
|
echo "Yes"
|
|
else
|
|
echo "No"
|
|
fi
|
|
}
|
|
|
|
menulist() {
|
|
# Args: menu options.
|
|
# returns: selected tag
|
|
local i
|
|
local menuList
|
|
for i in "$@" ; do
|
|
menuList+=("$i" "$i")
|
|
done
|
|
dialog --backtitle "$(gettext "Use the up and down arrow keys to find the option you want, then press enter to select it.")" \
|
|
--clear \
|
|
--no-tags \
|
|
--menu "$(gettext "Please select one")" 0 0 0 "${menuList[@]}" --stdout
|
|
}
|
|
|
|
[[ -d ~/.config/barnard ]] || mkdir ~/.config/barnard
|
|
if [[ ! -r ~/.config/barnard/servers.conf ]]; then
|
|
echo "Adding default mumble server." | log
|
|
echo "declare -Ag mumbleServerList=(" > ~/.config/barnard/servers.conf
|
|
echo "[Slint]=\"slint.fr:64738 -insecure\"" >> ~/.config/barnard/servers.conf
|
|
echo ")" >> ~/.config/barnard/servers.conf
|
|
fi
|
|
source ~/.config/barnard/servers.conf
|
|
|
|
function add-server() {
|
|
local serverName="$(inputbox "$(gettext "Enter a name for the new server:")")"
|
|
[[ $? -ne 0 ]] && return
|
|
local serverAddress="$(inputbox "$(gettext "Enter the address of the server. If there is a password, do it in the form, password@address, if the port is not standard, add it after a :, address:port:")")"
|
|
[[ $? -ne 0 ]] && return
|
|
local serverPassword="${serverAddress%@*}"
|
|
local serverAddress="${serverAddress#*@}"
|
|
local serverPort="${serverAddress##*:}"
|
|
local serverAddress="${serverAddress%:*}"
|
|
if ! [[ "$serverPort" =~ ^[0-9]+ ]]; then
|
|
serverPort=64738
|
|
fi
|
|
mumbleServerList[$serverName]="${serverAddress}:${serverPort}${serverPassword:+ -password ${serverPassword}}"
|
|
echo "declare -Ag mumbleServerList=(" > ~/.config/barnard/servers.conf
|
|
for i in "${!mumbleServerList[@]}" ; do
|
|
echo "[${i}]=\"${mumbleServerList[$i]}\"" >> ~/.config/barnard/servers.conf
|
|
done
|
|
echo ")" >> ~/.config/barnard/servers.conf
|
|
echo "Added server $serverName ${serverAddress}:${serverPort}" | log
|
|
msgbox "$(gettext "Added server") $serverName"
|
|
}
|
|
|
|
connect() {
|
|
ifs="$IFS"
|
|
IFS=$'\n'
|
|
local serverName
|
|
serverName="$(menulist "${!mumbleServerList[@]}" "Go Back")"
|
|
[[ $? -eq 1 ]] && exit 0
|
|
IFS="$ifs"
|
|
if [[ -z "$serverName" || "$serverName" == "Go Back" ]]; then
|
|
return
|
|
fi
|
|
local username
|
|
username="$(grep -m 1 '^Username = ' ~/.barnard.toml 2> /dev/null | cut -d '=' -f2- | sed "s/^[[:space:]]*//;s/[[:space:]]*$//;s/'//g")"
|
|
username="${username//[[:space:]]/_}"
|
|
username="${username:-${USER}-${HOSTNAME}}"
|
|
local certArgs=()
|
|
if [[ -f "$certFile" ]]; then
|
|
certArgs=(-certificate "$certFile")
|
|
fi
|
|
# shellcheck disable=SC2086
|
|
command barnard -username "$username" -server ${mumbleServerList[$serverName]} "${certArgs[@]}" --fifo ~/.config/barnard/cmd --buffers 16 |& log
|
|
}
|
|
|
|
remove-server() {
|
|
ifs="$IFS"
|
|
IFS=$'\n'
|
|
local serverName="$(menulist "${!mumbleServerList[@]}" "Go Back")"
|
|
IFS="$ifs"
|
|
if [[ -z "$serverName" || "$serverName" == "Go Back" ]]; then
|
|
return
|
|
fi
|
|
unset "mumbleServerList[$serverName]"
|
|
echo "declare -Ag mumbleServerList=(" > ~/.config/barnard/servers.conf
|
|
for i in "${!mumbleServerList[@]}" ; do
|
|
echo "[${i}]=\"${mumbleServerList[$i]}\"" >> ~/.config/barnard/servers.conf
|
|
done
|
|
echo ")" >> ~/.config/barnard/servers.conf
|
|
echo "Removed server $serverName ${serverAddress}:${serverPort}" | log
|
|
msgbox "$(gettext "Removed server") $serverName"
|
|
}
|
|
|
|
# Certificate configuration
|
|
certDir="$HOME/.config/barnard"
|
|
certFile="$certDir/barnard.pem"
|
|
|
|
generate-certificate() {
|
|
if [[ -f "$certFile" ]]; then
|
|
if [[ "$(yesno "$(gettext "A certificate already exists. Do you want to replace it? This may affect your registered identity on servers.")")" != "Yes" ]]; then
|
|
return
|
|
fi
|
|
fi
|
|
local commonName
|
|
commonName="$(inputbox "$(gettext "Enter a name for your certificate (e.g., your username):")" "barnard")"
|
|
[[ $? -ne 0 ]] && return
|
|
[[ -z "$commonName" ]] && commonName="barnard"
|
|
|
|
if openssl req -x509 -newkey rsa:2048 -keyout "$certFile" -out "$certFile" -days 3650 -nodes -subj "/CN=$commonName" 2>/dev/null; then
|
|
chmod 600 "$certFile"
|
|
msgbox "$(gettext "Certificate generated successfully.")"
|
|
else
|
|
msgbox "$(gettext "Failed to generate certificate. Make sure openssl is installed.")"
|
|
fi
|
|
}
|
|
|
|
view-certificate() {
|
|
if [[ ! -f "$certFile" ]]; then
|
|
msgbox "$(gettext "No certificate found.") $certFile"
|
|
return
|
|
fi
|
|
local certInfo
|
|
certInfo=$(openssl x509 -in "$certFile" -noout -subject -dates -fingerprint 2>/dev/null)
|
|
if [[ -n "$certInfo" ]]; then
|
|
msgbox "$certInfo"
|
|
else
|
|
msgbox "$(gettext "Could not read certificate information.")"
|
|
fi
|
|
}
|
|
|
|
import-certificate() {
|
|
local importPath
|
|
importPath="$(inputbox "$(gettext "Enter the full path to your certificate file (PEM format with certificate and private key):")")"
|
|
[[ $? -ne 0 ]] && return
|
|
[[ -z "$importPath" ]] && return
|
|
|
|
# Expand ~ if present
|
|
importPath="${importPath/#\~/$HOME}"
|
|
|
|
if [[ ! -f "$importPath" ]]; then
|
|
msgbox "$(gettext "File not found:") $importPath"
|
|
return
|
|
fi
|
|
|
|
# Verify it's a valid certificate
|
|
if ! openssl x509 -in "$importPath" -noout 2>/dev/null; then
|
|
msgbox "$(gettext "The file does not appear to be a valid PEM certificate.")"
|
|
return
|
|
fi
|
|
|
|
# Verify it contains a private key
|
|
if ! openssl rsa -in "$importPath" -check -noout 2>/dev/null && ! openssl ec -in "$importPath" -check -noout 2>/dev/null; then
|
|
msgbox "$(gettext "The file does not appear to contain a valid private key. The certificate file must contain both the certificate and private key.")"
|
|
return
|
|
fi
|
|
|
|
if [[ -f "$certFile" ]]; then
|
|
if [[ "$(yesno "$(gettext "A certificate already exists. Do you want to replace it?")")" != "Yes" ]]; then
|
|
return
|
|
fi
|
|
fi
|
|
|
|
if cp "$importPath" "$certFile" && chmod 600 "$certFile"; then
|
|
msgbox "$(gettext "Certificate imported successfully.")"
|
|
else
|
|
msgbox "$(gettext "Failed to import certificate.")"
|
|
fi
|
|
}
|
|
|
|
manage-certificate() {
|
|
while : ; do
|
|
local certAction
|
|
certAction="$(menulist "Generate" "View" "Import" "Go_Back")"
|
|
[[ $? -eq 1 ]] && return
|
|
case "$certAction" in
|
|
"Generate") generate-certificate ;;
|
|
"View") view-certificate ;;
|
|
"Import") import-certificate ;;
|
|
"Go_Back"|"") return ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# main menu
|
|
while : ; do
|
|
action="$(menulist "Connect" "Add_server" "Remove_server" "Manage_Certificate")"
|
|
[[ $? -eq 1 ]] && exit 0
|
|
action="${action,,}"
|
|
action="${action//_/-}"
|
|
if [[ "$action" == "exit" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
eval "$action"
|
|
|
|
done
|