| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736 | #!/bin/bash
#
# .---.                  .              .
# |                      |              |
# |--- .--. .-.  .-.  .-.|  .-. .--.--. |.-.  .-. .--.  .-.
# |    |   (.-' (.-' (   | (   )|  |  | |   )(   )|  | (.-'
# '    '     --'  --'  -' -  -' '  '   -' -'   -' '   -  --'
#
#                    Freedom in the Cloud
#
# Administrator control panel for the Freedombone system
#
# License
# =======
#
# Copyright (C) 2015-2016 Bob Mottram <bob@robotics.uk.to>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
PROJECT_NAME='freedombone'
export TEXTDOMAIN=${PROJECT_NAME}-controlpanel
export TEXTDOMAINDIR="/usr/share/locale"
COMPLETION_FILE=$HOME/${PROJECT_NAME}-completed.txt
SELECTED_USERNAME=
SIP_CONFIGURATION_FILE=/etc/sipwitch.conf
ADMIN_USER=
UPGRADE_SCRIPT_NAME="${PROJECT_NAME}-upgrade"
UPDATE_DATE_SCRIPT=/usr/bin/updatedate
# Minimum number of characters in a password
MINIMUM_PASSWORD_LENGTH=8
# voip
VOIP_PORT=64738
VOIP_ONION_PORT=8095
SSH_PORT=2222
IRC_PORT=6697
IRC_ONION_PORT=8093
USB_DRIVE=sdb
# get default USB from config file
CONFIGURATION_FILE=/root/${PROJECT_NAME}.cfg
if [ -f $CONFIGURATION_FILE ]; then
    if grep -q "USB_DRIVE=" $CONFIGURATION_FILE; then
        USB_DRIVE=$(cat $CONFIGURATION_FILE | grep "USB_DRIVE=" | awk -F '=' '{print $2}')
        if [[ $USB_DRIVE == *"dev"* ]]; then
            USB_DRIVE=$(echo ${USB_DRIVE} | awk -F '/' '{print $3}' | sed 's|1||g' | sed 's|2||g')
        fi
    fi
    if grep -q "SSH_PORT=" $CONFIGURATION_FILE; then
        SSH_PORT=$(cat $CONFIGURATION_FILE | grep "SSH_PORT=" | awk -F '=' '{print $2}')
    fi
    if grep -q "IRC_PORT=" $CONFIGURATION_FILE; then
        IRC_PORT=$(cat $CONFIGURATION_FILE | grep "IRC_PORT=" | awk -F '=' '{print $2}')
    fi
fi
# Mirrors settings
FRIENDS_MIRRORS_SERVER=
FRIENDS_MIRRORS_SSH_PORT=2222
FRIENDS_MIRRORS_PASSWORD=
MY_MIRRORS_PASSWORD=
function any_key {
    echo ' '
    read -n1 -r -p $"Press any key to continue..." key
}
function check_for_updates {
    if [ ! -f /etc/cron.weekly/$UPGRADE_SCRIPT_NAME ]; then
        dialog --title $"Check for updates" \
               --msgbox $"Upgrade script was not found" 6 40
        return
    fi
    clear
    . /etc/cron.weekly/$UPGRADE_SCRIPT_NAME
    any_key
}
function read_repo_servers {
    if [ -f $CONFIGURATION_FILE ]; then
        if grep -q "FRIENDS_MIRRORS_SERVER" $CONFIGURATION_FILE; then
            FRIENDS_MIRRORS_SERVER=$(grep "FRIENDS_MIRRORS_SERVER" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
        fi
        if grep -q "FRIENDS_MIRRORS_SSH_PORT" $CONFIGURATION_FILE; then
            FRIENDS_MIRRORS_SSH_PORT=$(grep "FRIENDS_MIRRORS_SSH_PORT" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
        fi
        if grep -q "MY_MIRRORS_PASSWORD" $CONFIGURATION_FILE; then
            MY_MIRRORS_PASSWORD=$(grep "MY_MIRRORS_PASSWORD" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
        fi
        if grep -q "FRIENDS_MIRRORS_PASSWORD" $CONFIGURATION_FILE; then
            FRIENDS_MIRRORS_PASSWORD=$(grep "FRIENDS_MIRRORS_PASSWORD" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
        fi
    fi
    if [ ! $FRIENDS_MIRRORS_SERVER ]; then
        return
    fi
    if [ ${#FRIENDS_MIRRORS_SERVER} -lt 2 ]; then
        return
    fi
    MAIN_COMMAND=/usr/local/bin/${PROJECT_NAME}
    if [ ! -f $MAIN_COMMAND ]; then
        MAIN_COMMAND=/usr/bin/${PROJECT_NAME}
    fi
    REPOS=($(cat ${MAIN_COMMAND} | grep "_REPO=\"" | uniq -u | sed 's|${PROJECT_NAME}|'"${PROJECT_NAME}"'|g'))
    for line in "${REPOS[@]}"
    do
        repo_name=$(echo "$line" | awk -F '=' '{print $1}')
        mirrors_name=$(echo "$repo_name" | sed "s|_REPO||g" | awk '{print tolower($0)}')
        friends_repo_url="ssh://mirrors@${FRIENDS_MIRRORS_SERVER}:${FRIENDS_MIRRORS_SSH_PORT}/home/mirrors/${mirrors_name}"
        ${repo_name}="${friends_repo_url}"
    done
}
function set_main_repo {
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Main Repository (Mirrors)" \
           --form $"If you do not wish to use the default repositories they can be obtained from mirrors on another ${PROJECT_NAME} server." 14 60 3 \
              $"URL:" 1 1 "$FRIENDS_MIRRORS_SERVER" 1 14 40 15 \
              $"SSH Port:" 2 1 "$FRIENDS_MIRRORS_SSH_PORT" 2 14 40 10000 \
              $"Password:" 3 1 "$FRIENDS_MIRRORS_PASSWORD" 3 14 40 10000 \
              2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    new_mirrors_url=$(cat $data | sed -n 1p)
    new_mirrors_ssh_port=$(cat $data | sed -n 2p)
    new_mirrors_password=$(cat $data | sed -n 3p)
    if [ ${#new_mirrors_url} -lt 2 ]; then
        return
    fi
    if [ ${#new_mirrors_ssh_port} -lt 1 ]; then
        return
    fi
    if [ ${#new_mirrors_password} -lt 10 ]; then
        dialog --title $"Main Repository" \
               --msgbox $'Mirrors password was too short. Should be at least 10 characters.' 6 40
        return
    fi
    if [[ $new_mirrors_url == *"."* ]]; then
        FRIENDS_MIRRORS_SERVER=$new_mirrors_url
        FRIENDS_MIRRORS_SSH_PORT=$new_mirrors_ssh_port
        FRIENDS_MIRRORS_PASSWORD=$new_mirrors_password
        if ! grep -q "FRIENDS_MIRRORS_SERVER" $CONFIGURATION_FILE; then
            echo "FRIENDS_MIRRORS_SERVER=$FRIENDS_MIRRORS_SERVER" >> $CONFIGURATION_FILE
        else
            sed -i "s|FRIENDS_MIRRORS_SERVER=.*|FRIENDS_MIRRORS_SERVER=$FRIENDS_MIRRORS_SERVER|g" $CONFIGURATION_FILE
        fi
        if ! grep -q "FRIENDS_MIRRORS_SSH_PORT" $CONFIGURATION_FILE; then
            echo "FRIENDS_MIRRORS_SSH_PORT=$FRIENDS_MIRRORS_SSH_PORT" >> $CONFIGURATION_FILE
        else
            sed -i "s|FRIENDS_MIRRORS_SSH_PORT=.*|FRIENDS_MIRRORS_SSH_PORT=$FRIENDS_MIRRORS_SSH_PORT|g" $CONFIGURATION_FILE
        fi
        if ! grep -q "FRIENDS_MIRRORS_PASSWORD" $CONFIGURATION_FILE; then
            echo "FRIENDS_MIRRORS_PASSWORD=$FRIENDS_MIRRORS_PASSWORD" >> $CONFIGURATION_FILE
        else
            sed -i "s|FRIENDS_MIRRORS_PASSWORD=.*|FRIENDS_MIRRORS_PASSWORD=$FRIENDS_MIRRORS_PASSWORD|g" $CONFIGURATION_FILE
        fi
        # re-read the repos
        read_repo_servers
        dialog --title $"Main Repository" \
               --msgbox $"Main repository set to $FRIENDS_MIRRORS_SERVER" 6 60
    fi
}
function add_user {
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Add new user" \
           --form "\n" 8 60 3 \
              $"Username:" 1 1 "" 1 28 16 15 \
              $"ssh public key (optional):" 2 1 "" 2 28 40 10000 \
              2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    new_user_username=$(cat $data | sed -n 1p)
    new_user_ssh_public_key=$(cat $data | sed -n 2p)
    if [ ${#new_user_username} -lt 2 ]; then
        dialog --title $"New username" \
               --msgbox $"No username was given" 6 40
        return
    fi
    if [[ "$new_user_username" == *" "* ]]; then
        dialog --title $"Invalid username" \
               --msgbox $"The username should not contain any spaces" 6 40
        return
    fi
    if [ ${#new_user_ssh_public_key} -lt 20 ]; then
        clear
        ${PROJECT_NAME}-adduser "$new_user_username"
        any_key
    else
        if [[ "$new_user_ssh_public_key" == "ssh-"* ]]; then
            clear
            ${PROJECT_NAME}-adduser "$new_user_username" "$new_user_ssh_public_key"
            any_key
        else
            dialog --title $"ssh public key" \
                   --msgbox $"This does not look like an ssh public key" 6 40
        fi
    fi
}
function pad_string {
    echo -n -e "$1" | sed -e :a -e 's/^.\{1,25\}$/& /;ta'
}
function show_domains {
    DEFAULT_DOMAIN_NAME=$(cat $CONFIGURATION_FILE | grep "DEFAULT_DOMAIN_NAME=" | awk -F '=' '{print $2}')
    echo 'Domains'
    echo '======='
    echo ''
    echo -n -e "$(pad_string 'Name')"
    echo -n -e "$(pad_string 'ICANN')"
    echo -n -e "$(pad_string 'Tor')"
    echo ''
    echo '--------------------------------------------------------------------------'
    if grep -q "ssh onion domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'ssh')"
        echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
        echo "$(cat ${COMPLETION_FILE} | grep 'ssh onion domain' | awk -F ':' '{print $2}')"
    fi
    if grep -q "Email onion domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'Email')"
        echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
        echo "$(cat ${COMPLETION_FILE} | grep 'Email onion domain' | awk -F ':' '{print $2}')"
    fi
    if grep -q "XMPP onion domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'XMPP')"
        echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
        echo "$(cat ${COMPLETION_FILE} | grep 'XMPP onion domain' | awk -F ':' '{print $2}')"
    fi
    if grep -q "VoIP onion domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'VoIP/Mumble')"
        echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
        echo "$(cat ${COMPLETION_FILE} | grep 'VoIP onion domain' | awk -F ':' '{print $2}')"
    fi
    if grep -q "SIP onion domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'SIP')"
        echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
        echo "$(cat ${COMPLETION_FILE} | grep 'SIP onion domain' | awk -F ':' '{print $2}')"
    fi
    if grep -q "IRC onion domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'IRC')"
        echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
        echo "$(cat ${COMPLETION_FILE} | grep 'IRC onion domain' | awk -F ':' '{print $2}')"
    fi
    if grep -q "tox onion domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'Tox')"
        echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
        echo "$(cat ${COMPLETION_FILE} | grep 'tox onion domain' | awk -F ':' '{print $2}')"
    fi
    if grep -q "Wiki domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'Wiki')"
        WIKIDOM=$(cat ${COMPLETION_FILE} | grep 'Wiki domain' | awk -F ':' '{print $2}')
        echo -n -e "$(pad_string ${WIKIDOM})"
        if [ -d /var/lib/tor/hidden_service_wiki ]; then
            echo -n "$(cat /var/lib/tor/hidden_service_wiki/hostname)"
        fi
        echo ''
    fi
    if grep -q "Hubzilla domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'Hubzilla')"
        HUBZILLADOM=$(cat ${COMPLETION_FILE} | grep 'Hubzilla domain' | awk -F ':' '{print $2}')
        echo -n -e "$(pad_string ${HUBZILLADOM})"
        if [ -d /var/lib/tor/hidden_service_hubzilla ]; then
            echo -n "$(cat /var/lib/tor/hidden_service_hubzilla/hostname)"
        fi
        echo ''
    fi
    if grep -q "Blog domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'Blog')"
        BLOGDOM=$(cat ${COMPLETION_FILE} | grep 'Blog domain' | awk -F ':' '{print $2}')
        echo -n -e "$(pad_string ${BLOGDOM})"
        if [ -d /var/lib/tor/hidden_service_blog ]; then
            echo -n "$(cat /var/lib/tor/hidden_service_blog/hostname)"
        fi
        echo ''
    fi
    if grep -q "GNU Social domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'GNU Social')"
        GNUSOCIALDOM=$(cat ${COMPLETION_FILE} | grep 'GNU Social domain' | awk -F ':' '{print $2}')
        echo -n -e "$(pad_string ${GNUSOCIALDOM})"
        if [ -d /var/lib/tor/hidden_service_microblog ]; then
            echo -n "$(cat /var/lib/tor/hidden_service_microblog/hostname)"
        fi
        echo ''
    fi
    if grep -q "Owncloud domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'Owncloud')"
        OWNCLOUDDOM=$(cat ${COMPLETION_FILE} | grep 'Owncloud domain' | awk -F ':' '{print $2}')
        echo -n -e "$(pad_string ${OWNCLOUDDOM})"
        if [ -d /var/lib/tor/hidden_service_owncloud ]; then
            echo -n "$(cat /var/lib/tor/hidden_service_owncloud/hostname)"
        fi
        echo ''
    fi
    if grep -q "Gogs domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'Gogs')"
        GOGSDOM=$(cat ${COMPLETION_FILE} | grep 'Gogs domain' | awk -F ':' '{print $2}')
        echo -n -e "$(pad_string ${GOGSDOM})"
        if [ -d /var/lib/tor/hidden_service_gogs ]; then
            echo -n "$(cat /var/lib/tor/hidden_service_gogs/hostname)"
        fi
        echo ''
    fi
    if grep -q "RSS reader domain" $COMPLETION_FILE; then
        echo -n -e "$(pad_string 'RSS reader')"
        #RSSDOM=$(cat ${COMPLETION_FILE} | grep 'RSS reader domain' | awk -F ':' '{print $2}')
        RSSDOM='-'
        echo -n -e "$(pad_string ${RSSDOM})"
        if [ -d /var/lib/tor/hidden_service_ttrss ]; then
            echo -n "$(cat /var/lib/tor/hidden_service_ttrss/hostname)"
        fi
        echo ''
    fi
    echo ''
}
function show_users {
    echo 'Users'
    echo '====='
    echo ''
    echo -n -e "$(pad_string 'Name')"
    echo -n -e "$(pad_string 'SIP ext')"
    echo -n -e "$(pad_string 'Data')"
    echo ''
    echo '--------------------------------------------------------------------------'
    for d in /home/*/ ; do
        USRNAME=$(echo "$d" | awk -F '/' '{print $3}')
        if [[ $USRNAME != "git" && $USRNAME != "mirrors" ]]; then
            echo -n -e "$(pad_string ${USRNAME})"
            # get the SIP extension
            SIPEXT=
            while read ext; do
                if [[ $ext == *"user id"* ]]; then
                    CURR_UID=$(echo "$ext" | awk -F '"' '{print $2}' | awk -F '"' '{print $1}')
                fi
                if [[ $ext == *"extension"* ]]; then
                    if [[ $CURR_UID == $USRNAME ]]; then
                        SIPEXT=$(echo "$ext" | awk -F '>' '{print $2}' | awk -F '<' '{print $1}')
                    fi
                fi
            done < $SIP_CONFIGURATION_FILE
            if [ $SIPEXT ]; then
                echo -n -e "$(pad_string SIP:${SIPEXT})"
            else
                echo -n -e "$(pad_string '')"
            fi
            # size of the home directory
            echo "$(du -s -h /home/${USRNAME} | awk -F ' ' '{print $1}')"
        fi
    done
    echo ''
}
function show_mirrors_password {
    if [ ! /home/mirrors ]; then
        return
    fi
    if grep -q "MY_MIRRORS_PASSWORD" $CONFIGURATION_FILE; then
        MY_MIRRORS_PASSWORD=$(grep "MY_MIRRORS_PASSWORD" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
    fi
    echo 'Local Mirrors'
    echo '============='
    echo ''
    echo -n "URL:      "
    echo "$(cat ${COMPLETION_FILE} | grep 'ssh onion domain' | awk -F ':' '{print $2}')"
    echo "SSH Port: $SSH_PORT"
    echo "Password: $MY_MIRRORS_PASSWORD"
    echo ''
}
function show_about {
    clear
    show_domains
    show_mirrors_password
    show_users
    any_key
}
function select_user {
    SELECTED_USERNAME=
    users_array=($(ls /home))
    delete=(mirrors git)
    for del in ${delete[@]}
    do
        users_array=(${users_array[@]/$del})
    done
    i=0
    W=()
    name=()
    for u in ${users_array[@]}
    do
        i=$((i+1))
        W+=($i "$u")
        name+=("$u")
    done
    user_index=$(dialog --backtitle $"Freedombone Control Panel" --title $"Select User" --menu $"Select one of the following:" 24 40 17 "${W[@]}" 3>&2 2>&1 1>&3)
    if [ $? -eq 0 ]; then
        SELECTED_USERNAME="${name[$((user_index-1))]}"
    fi
}
function delete_user {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    if grep -Fxq "Admin user:$SELECTED_USERNAME" $COMPLETION_FILE; then
        dialog --title $"Administrator user" \
               --msgbox $"You can't delete the administrator user" 6 40
        return
    fi
    clear
    ${PROJECT_NAME}-rmuser $SELECTED_USERNAME
    any_key
}
function configure_remote_backups {
    if ! grep -Fxq "Admin user:$ADMIN_USER" $COMPLETION_FILE; then
        dialog --title $"Administrator user" \
               --msgbox $"No Administrator user found. Check $COMPLETION_FILE" 6 40
        return
    fi
    if [ ${#ADMIN_USER} -lt 2 ]; then
        dialog --title $"Administrator user" \
               --msgbox $"Username not found" 6 40
        return
    fi
    if [ ! -d /home/$ADMIN_USER ]; then
        dialog --title $"Administrator user" \
               --msgbox $"Home directory not found" 6 40
        return
    fi
    ${PROJECT_NAME}-remote -u $ADMIN_USER
    if [ ! "$?" = "0" ]; then
        any_key
    fi
}
function change_password {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    dialog --title $"Change password" \
           --passwordbox $"New password for user $SELECTED_USERNAME" 8 40 2> $data
    newpassword=$(<$data)
    if [ ${#newpassword} -lt ${MINIMUM_PASSWORD_LENGTH} ]; then
        dialog --title $"Change password" \
               --msgbox $"The password should be ${MINIMUM_PASSWORD_LENGTH} or more characters" 6 40
        return
    fi
    echo "$SELECTED_USERNAME:$newpassword"|chpasswd
    dialog --title $"Change password" \
           --msgbox $"Password for $SELECTED_USERNAME was changed" 6 40
}
function irc_set_global_password {
    dialog --title $"IRC Password" \
           --clear \
           --backtitle $"Freedombone Control Panel" \
           --passwordbox $"Password for all IRC users, or press Enter for no password" 10 50 2> $data
    sel=$?
    case $sel in
        0)
            NEW_IRC_PASSWORD=$(<$data)
            sed -i "0,/RE/s/Password =.*/Password =$NEW_IRC_PASSWORD/" /etc/ngircd/ngircd.conf
            dialog --title $"IRC Password" \
                   --msgbox $"The IRC password was changed" 6 40
            ;;
    esac
}
function change_ssh_public_key {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    if grep -Fxq "Admin user:$SELECTED_USERNAME" $COMPLETION_FILE; then
        dialog --title $"Change ssh public key" \
               --backtitle $"Freedombone Control Panel" \
               --defaultno \
               --yesno $"\nThis is the administrator user.\n\nAre you sure you want to change the ssh public key for the administrator?" 10 60
        sel=$?
        case $sel in
            1) return;;
            255) return;;
        esac
    fi
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --title $"Change ssh public key for $SELECTED_USERNAME" \
           --backtitle $"Freedombone Control Panel" \
           --inputbox $"Paste the ssh public key below" 8 60 2>$data
    sel=$?
    case $sel in
        0)
            SSH_PUBLIC_KEY=$(<$data)
            if [ "$SSH_PUBLIC_KEY" ]; then
                if [ ${#SSH_PUBLIC_KEY} -gt 5 ]; then
                    if [ -f "$SSH_PUBLIC_KEY" ]; then
                        if [ ! -d /home/$SELECTED_USERNAME/.ssh ]; then
                            mkdir /home/$SELECTED_USERNAME/.ssh
                        fi
                        cp $SSH_PUBLIC_KEY \
                           /home/$SELECTED_USERNAME/.ssh/authorized_keys
                        chown -R $SELECTED_USERNAME:$SELECTED_USERNAME \
                              /home/$SELECTED_USERNAME/.ssh
                        dialog --title $"Change ssh public key" \
                               --msgbox $"ssh public key was installed" 6 40
                    else
                        if [[ "$SSH_PUBLIC_KEY" == "ssh-"* ]]; then
                            if [ ! -d /home/$SELECTED_USERNAME/.ssh ]; then
                                mkdir /home/$SELECTED_USERNAME/.ssh
                            fi
                            echo "$SSH_PUBLIC_KEY" > \
                                 /home/$SELECTED_USERNAME/.ssh/authorized_keys
                            chown -R $SELECTED_USERNAME:$SELECTED_USERNAME \
                                  /home/$SELECTED_USERNAME/.ssh
                            dialog --title $"Change ssh public key" \
                                   --msgbox $"ssh public key was installed" 6 40
                        fi
                    fi
                fi
            fi
            ;;
    esac
}
function irc_via_onion {
    dialog --title $"IRC Server" \
           --backtitle $"Freedombone Control Panel" \
           --defaultno \
           --yesno $"\nAccess the IRC server via an onion address?" 8 60
    sel=$?
    irc_onion='no'
    case $sel in
        0) irc_onion='yes';;
        255) return;;
    esac
    if [[ $irc_onion == 'no' ]]; then
        if grep -q ";Ports = 6667" /etc/ngircd/ngircd.conf; then
            sed -i "s/;Ports =.*/;Ports = $IRC_PORT, $IRC_ONION_PORT/1" /etc/ngircd/ngircd.conf
        else
            if ! grep -q ";Ports = $IRC_PORT, $IRC_ONION_PORT" /etc/ngircd/ngircd.conf; then
                sed -i "s/Ports = $IRC_PORT, $IRC_ONION_PORT/;Ports = $IRC_PORT, $IRC_ONION_PORT/1" /etc/ngircd/ngircd.conf
            fi
        fi
        systemctl restart ngircd
        dialog --title $"IRC Server" \
               --msgbox $"The IRC server can now be accessed via SSL at your main domain name" 8 50
    else
        if grep -q ";Ports = $IRC_PORT, $IRC_ONION_PORT" /etc/ngircd/ngircd.conf; then
            sed -i "s/;Ports =.*/Ports = $IRC_PORT, $IRC_ONION_PORT/1" /etc/ngircd/ngircd.conf
            systemctl restart ngircd
        fi
        dialog --title $"IRC Server" \
               --msgbox $"The IRC server can now be accessed via its onion address without SSL" 8 50
    fi
}
function remove_user_from_mailing_list {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    USER_MAILING_LISTS=$(cat "/home/$SELECTED_USERNAME/.procmailrc" | grep '\[' | grep '\]' | awk -F '\[' '{print $2}' | awk -F '\\' '{print $1}')
    i=0
    W=()
    list_name=()
    while read -r listname; do
        i=$((i+1))
        W+=($i "$listname")
        list_name+=("$listname")
        echo $listname
    done <<< "$USER_MAILING_LISTS"
    i=$((i+1))
    W+=($i $"Exit back to user mainenance")
    list_selected=$(dialog --default-item "$i" --backtitle $"Freedombone Control Panel" --title $"Remove a mailing list for $SELECTED_USERNAME" --menu $"Select one of the following:" 24 50 17 "${W[@]}" 3>&2 2>&1 1>&3)
    if [ $? -eq 0 ]; then # Exit with OK
        if [ ${list_selected} -ne ${i} ]; then
            remove_list_name="${list_name[$((list_selected-1))]}"
            # find the line number where the list is defined
            line_number=0
            i=0
            while read -r line
            do
                if [[ "$line" == *"\[${remove_list_name}\\]"* ]]; then
                    line_number=${i}
                fi
                i=$((i+1))
            done < "/home/$SELECTED_USERNAME/.procmailrc"
            if [ ${line_number} -eq 0 ]; then
                # no match was found
                return
            fi
            # recreate the file
            if [ -f /home/${SELECTED_USERNAME}/.procmailrc_new ]; then
                rm /home/${SELECTED_USERNAME}/.procmailrc_new
            fi
            i=0
            clip=0
            while read -r line
            do
                i=$((i+1))
                if [ ${i} -gt $((line_number-1)) ]; then
                    if [ ${clip} -eq 0 ]; then
                        clip=1
                    fi
                    if [ ${clip} -eq 1 ]; then
                        if [ ${i} -lt $((line_number+2)) ]; then
                            continue
                        else
                            if [ ${#line} -lt 1 ]; then
                                clip=2
                                continue
                            fi
                            if [[ "$line" == ":"* || "$line" == "#"* ]]; then
                                clip=2
                            else
                                continue
                            fi
                        fi
                    fi
                fi
                echo "$line" >> /home/${SELECTED_USERNAME}/.procmailrc_new
                if [[ "$line" == *"\[${remove_list_name}\\]"* ]]; then
                    line_number=${i}
                fi
            done < "/home/$SELECTED_USERNAME/.procmailrc"
            cp /home/${SELECTED_USERNAME}/.procmailrc_new /home/${SELECTED_USERNAME}/.procmailrc
            rm /home/${SELECTED_USERNAME}/.procmailrc_new
            chown ${SELECTED_USERNAME}:${SELECTED_USERNAME} /home/${SELECTED_USERNAME}/.procmailrc
            dialog --title $"Remove user from mailing list" \
                   --msgbox $"${SELECTED_USERNAME} has been removed from ${remove_list_name}" 6 50
        fi
    fi
}
function add_to_mailing_list {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Subscribe $SELECTED_USERNAME to a mailing list" \
           --form $"You can either enter a subject or an email address\n" 11 68 4 \
              $"List folder name:" 1 1 "" 1 35 26 25 \
              $"Name between [] on subject line:" 2 1 "" 2 35 26 25 \
              $"List email address:" 3 1 "" 3 35 26 25 \
              $"Public:" 4 1 $"yes" 4 35 4 25 \
              2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    LIST_NAME=$(cat $data | sed -n 1p)
    LIST_SUBJECT=$(cat $data | sed -n 2p)
    LIST_EMAIL=$(cat $data | sed -n 3p)
    LIST_PUBLIC=$(cat $data | sed -n 4p)
    if [ ${#LIST_PUBLIC} -lt 1 ]; then
        LIST_PUBLIC='no'
    fi
    if [[ $LIST_PUBLIC == $'y' || $LIST_PUBLIC == $'Y' || $LIST_PUBLIC == $'true' || $LIST_PUBLIC == $'True' || $LIST_PUBLIC == $'yes' || $LIST_PUBLIC == $'Yes' || $LIST_PUBLIC == $'YES' ]]; then
        LIST_PUBLIC='yes'
    else
        LIST_PUBLIC='no'
    fi
    if [ ${#LIST_NAME} -lt 2 ]; then
        dialog --title $"Add mailing list" \
               --msgbox $"No mailing list name was given" 6 40
        return
    fi
    if [ ${#LIST_SUBJECT} -lt 2 ]; then
        if [ ${#LIST_EMAIL} -lt 2 ]; then
            dialog --title $"Add mailing list" \
                   --msgbox $"No mailing list subject or address was given" 6 40
            return
        fi
    fi
    if [ ${#LIST_SUBJECT} -gt 1 ]; then
        ${PROJECT_NAME}-addlist -u $SELECTED_USERNAME -l "$LIST_NAME" \
                       -s "$LIST_SUBJECT" --public $LIST_PUBLIC
    else
        if [[ "$LIST_EMAIL" != *"@"* || "$LIST_EMAIL" != *"."* ]]; then
            dialog --title $"Add mailing list" \
                   --msgbox $"Unrecognised email address" 6 40
            return
        else
            ${PROJECT_NAME}-addlist -u $SELECTED_USERNAME -l "$LIST_NAME" \
                           -e "$LIST_EMAIL" --public $LIST_PUBLIC
        fi
    fi
    dialog --title $"Add mailing list" \
           --msgbox $"$LIST_NAME list was added" 6 40
}
function email_rule {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Email rule for user $SELECTED_USERNAME" \
           --form "\n" 9 65 4 \
              $"When email arrives from address:" 1 1 "" 1 35 24 28 \
              $"Move to folder:" 2 1 "" 2 35 24 28 \
              $"Public:" 3 1 $"no" 3 35 4 25 \
              2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    RULE_EMAIL=$(cat $data | sed -n 1p)
    RULE_FOLDER=$(cat $data | sed -n 2p)
    RULE_PUBLIC=$(cat $data | sed -n 3p)
    if [ ${#RULE_PUBLIC} -lt 1 ]; then
        RULE_PUBLIC='no'
    fi
    if [[ $RULE_PUBLIC == $'y' || $RULE_PUBLIC == $'Y' || $RULE_PUBLIC == $'true' || $RULE_PUBLIC == $'True' || $RULE_PUBLIC == $'yes' || $RULE_PUBLIC == $'Yes' || $RULE_PUBLIC == $'YES' ]]; then
        RULE_PUBLIC='yes'
    else
        RULE_PUBLIC='no'
    fi
    if [ ${#RULE_EMAIL} -lt 2 ]; then
        dialog --title $"Add email rule" \
               --msgbox $"No email address was given" 6 40
        return
    fi
    if [ ${#RULE_FOLDER} -lt 2 ]; then
        dialog --title $"Add email rule" \
               --msgbox $"No folder name was given" 6 40
        return
    fi
    if [[ "$RULE_EMAIL" != *"@"* || "$RULE_EMAIL" != *"."* ]]; then
        dialog --title $"Add email rule" \
               --msgbox $"Unrecognised email address" 6 40
        return
    fi
    ${PROJECT_NAME}-addemail -u $SELECTED_USERNAME -e "$RULE_EMAIL" \
                         -g "$RULE_FOLDER" --public $RULE_PUBLIC
    dialog --title $"Add email rule" \
           --msgbox $"Email rule for $RULE_EMAIL was added" 6 40
}
function block_unblock_email {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    blockstr=$"Block/Unblock email going to"
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title "$blockstr $SELECTED_USERNAME" \
           --form "\n" 8 65 3 \
              $"When email arrives from address:" 1 1 "" 1 35 24 28 \
              $"Block it:" 2 1 "yes" 2 35 4 4 \
              2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    BLOCK_EMAIL=$(cat $data | sed -n 1p)
    BLOCK=$(cat $data | sed -n 2p)
    if [ ${#BLOCK_EMAIL} -lt 2 ]; then
        dialog --title $"Block/Unblock an email" \
               --msgbox $"No email address was given" 6 40
        return
    fi
    if [[ "$BLOCK_EMAIL" != *"@"* || "$BLOCK_EMAIL" != *"."* ]]; then
        dialog --title $"Block/Unblock an email" \
               --msgbox $"Unrecognised email address" 6 40
        return
    fi
    if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
        ${PROJECT_NAME}-ignore -u $SELECTED_USERNAME -e "$BLOCK_EMAIL"
        dialog --title $"Block an email" \
               --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME blocked" 6 40
    else
        ${PROJECT_NAME}-unignore -u $SELECTED_USERNAME -e "$BLOCK_EMAIL"
        dialog --title $"Unblock an email" \
               --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME unblocked" 6 40
    fi
}
function block_unblock_subject {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    blockstr=$"Block/Unblock email going to"
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title "$blockstr $SELECTED_USERNAME" \
           --form "\n" 8 70 3 \
              $"When email arrives with subject text:" 1 1 "" 1 40 24 28 \
              $"Block it:" 2 1 "yes" 2 40 4 4 \
              2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    BLOCK_SUBJECT=$(cat $data | sed -n 1p)
    BLOCK=$(cat $data | sed -n 2p)
    if [ ${#BLOCK_SUBJECT} -lt 2 ]; then
        dialog --title $"Block/Unblock an email" \
               --msgbox $"No subject was given" 6 40
        return
    fi
    if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
        ${PROJECT_NAME}-ignore -u $SELECTED_USERNAME -t "$BLOCK_SUBJECT"
        dialog --title $"Block an email" \
               --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME blocked" 6 40
    else
        ${PROJECT_NAME}-unignore -u $SELECTED_USERNAME -t "$BLOCK_SUBJECT"
        dialog --title $"Unblock an email" \
               --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME unblocked" 6 40
    fi
}
function create_keydrive_master {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    dialog --title $"USB Master Keydrive" \
           --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
    clear
    ${PROJECT_NAME}-keydrive -u $SELECTED_USERNAME --master 'yes'
    any_key
}
function create_keydrive_fragment {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    dialog --title $"USB Fragment Keydrive" \
           --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
    clear
    ${PROJECT_NAME}-keydrive -u $SELECTED_USERNAME
    any_key
}
function backup_data {
    dialog --title $"Backup data to USB" \
           --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
    clear
    echo ' '
    echo $'Enter the passphrase for your LUKS encrypted backup drive:'
    ${PROJECT_NAME}-backup-local
    any_key
}
function restore_from_usb {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"Restore from USB backup" \
               --radiolist $"Choose an application to restore:" 30 70 27 \
               1 $"Everything" on \
               2 $"Return to the backup and restore menu" off \
               3 $"Configuration files" off \
               4 $"MariaDB settings" off \
               5 $"Let's Encrypt account" off \
               6 $"Mutt email client settings" off \
               7 $"GPG keys" off \
               8 $"Email processing rules" off \
               9 $"Spam filtering rules" off \
               10 $"Administrator's README file" off \
               11 $"IPFS" off \
               12 $"SSH keys" off \
               13 $"User configuration files" off \
               14 $"SSL/TLS certificates" off \
               15 $"Personal settings" off \
               16 $"Mailing List" off \
               17 $"XMPP chat" off \
               18 $"GNU Social" off \
               19 $"Hubzilla" off \
               20 $"Owncloud" off \
               21 $"Gogs" off \
               22 $"Wiki" off \
               23 $"Blog" off \
               24 $"CJDNS" off \
               25 $"Email" off \
               26 $"DLNA" off \
               27 $"VoIP" off \
               28 $"Tox" off 2> $data
        sel=$?
        case $sel in
            1) break;;
            255) break;;
        esac
        case $(cat $data) in
            1) ${PROJECT_NAME}-restore-local $USB_DRIVE;;
            2) return;;
            3) ${PROJECT_NAME}-restore-local $USB_DRIVE configuration;;
            4) ${PROJECT_NAME}-restore-local $USB_DRIVE mariadb;;
            5) ${PROJECT_NAME}-restore-local $USB_DRIVE letsencrypt;;
            6) ${PROJECT_NAME}-restore-local $USB_DRIVE mutt;;
            7) ${PROJECT_NAME}-restore-local $USB_DRIVE gpg;;
            8) ${PROJECT_NAME}-restore-local $USB_DRIVE procmail;;
            9) ${PROJECT_NAME}-restore-local $USB_DRIVE spamassassin;;
            10) ${PROJECT_NAME}-restore-local $USB_DRIVE readme;;
            11) ${PROJECT_NAME}-restore-local $USB_DRIVE ipfs;;
            12) ${PROJECT_NAME}-restore-local $USB_DRIVE ssh;;
            13) ${PROJECT_NAME}-restore-local $USB_DRIVE userconfig;;
            14) ${PROJECT_NAME}-restore-local $USB_DRIVE certs;;
            15) ${PROJECT_NAME}-restore-local $USB_DRIVE personal;;
            16) ${PROJECT_NAME}-restore-local $USB_DRIVE mailinglist;;
            17) ${PROJECT_NAME}-restore-local $USB_DRIVE xmpp;;
            18) ${PROJECT_NAME}-restore-local $USB_DRIVE gnusocial;;
            19) ${PROJECT_NAME}-restore-local $USB_DRIVE hubzilla;;
            20) ${PROJECT_NAME}-restore-local $USB_DRIVE owncloud;;
            21) ${PROJECT_NAME}-restore-local $USB_DRIVE gogs;;
            22) ${PROJECT_NAME}-restore-local $USB_DRIVE wiki;;
            23) ${PROJECT_NAME}-restore-local $USB_DRIVE blog;;
            24) ${PROJECT_NAME}-restore-local $USB_DRIVE cjdns;;
            25) ${PROJECT_NAME}-restore-local $USB_DRIVE email;;
            26) ${PROJECT_NAME}-restore-local $USB_DRIVE dlna;;
            27) ${PROJECT_NAME}-restore-local $USB_DRIVE voip;;
            28) ${PROJECT_NAME}-restore-local $USB_DRIVE tox;;
        esac
    done
    any_key
}
function restore_from_remote {
    remote_domain_name=$1
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"Restore from ${remote_domain_name}" \
               --radiolist $"Choose an application to restore:" 30 70 27 \
               1 $"Everything" on \
               2 $"Return to the backup and restore menu" off \
               3 $"Configuration files" off \
               4 $"MariaDB settings" off \
               5 $"Let's Encrypt account" off \
               6 $"Mutt email client settings" off \
               7 $"GPG keys" off \
               8 $"Email processing rules" off \
               9 $"Spam filtering rules" off \
               10 $"Administrator's README file" off \
               11 $"IPFS" off \
               12 $"SSH keys" off \
               13 $"User configuration files" off \
               14 $"SSL/TLS certificates" off \
               15 $"Personal settings" off \
               16 $"Mailing List" off \
               17 $"XMPP chat" off \
               18 $"GNU Social" off \
               19 $"Hubzilla" off \
               20 $"Owncloud" off \
               21 $"Gogs" off \
               22 $"Wiki" off \
               23 $"Blog" off \
               24 $"CJDNS" off \
               25 $"Email" off \
               26 $"DLNA" off \
               27 $"VoIP" off \
               28 $"Tox" off 2> $data
        sel=$?
        case $sel in
            1) break;;
            255) break;;
        esac
        case $(cat $data) in
            1) ${PROJECT_NAME}-restore-remote $remote_domain_name;;
            2) return;;
            3) ${PROJECT_NAME}-restore-remote $remote_domain_name configuration;;
            4) ${PROJECT_NAME}-restore-remote $remote_domain_name mariadb;;
            5) ${PROJECT_NAME}-restore-remote $remote_domain_name letsencrypt;;
            6) ${PROJECT_NAME}-restore-remote $remote_domain_name mutt;;
            7) ${PROJECT_NAME}-restore-remote $remote_domain_name gpg;;
            8) ${PROJECT_NAME}-restore-remote $remote_domain_name procmail;;
            9) ${PROJECT_NAME}-restore-remote $remote_domain_name spamassassin;;
            10) ${PROJECT_NAME}-restore-remote $remote_domain_name readme;;
            11) ${PROJECT_NAME}-restore-remote $remote_domain_name ipfs;;
            12) ${PROJECT_NAME}-restore-remote $remote_domain_name ssh;;
            13) ${PROJECT_NAME}-restore-remote $remote_domain_name userconfig;;
            14) ${PROJECT_NAME}-restore-remote $remote_domain_name certs;;
            15) ${PROJECT_NAME}-restore-remote $remote_domain_name personal;;
            16) ${PROJECT_NAME}-restore-remote $remote_domain_name mailinglist;;
            17) ${PROJECT_NAME}-restore-remote $remote_domain_name xmpp;;
            18) ${PROJECT_NAME}-restore-remote $remote_domain_name gnusocial;;
            19) ${PROJECT_NAME}-restore-remote $remote_domain_name hubzilla;;
            20) ${PROJECT_NAME}-restore-remote $remote_domain_name owncloud;;
            21) ${PROJECT_NAME}-restore-remote $remote_domain_name gogs;;
            22) ${PROJECT_NAME}-restore-remote $remote_domain_name wiki;;
            23) ${PROJECT_NAME}-restore-remote $remote_domain_name blog;;
            24) ${PROJECT_NAME}-restore-remote $remote_domain_name cjdns;;
            25) ${PROJECT_NAME}-restore-remote $remote_domain_name email;;
            26) ${PROJECT_NAME}-restore-remote $remote_domain_name dlna;;
            27) ${PROJECT_NAME}-restore-remote $remote_domain_name voip;;
            28) ${PROJECT_NAME}-restore-remote $remote_domain_name tox;;
        esac
    done
    any_key
}
function restore_data {
    dialog --title $"Restore data from USB" \
           --msgbox $"Plug in your backup USB drive" 6 40
    clear
    echo ' '
    echo $'Enter the passphrase for your LUKS encrypted backup drive:'
    restore_from_usb
}
function restore_data_remote {
    if [ ! $ADMIN_USER ]; then
        dialog --title $"Restore data from remote server" \
               --msgbox $"Unknown admin user" 6 40
        return
    fi
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --title $"Restore from remote server" \
           --backtitle $"Freedombone Control Panel" \
           --inputbox $"Enter the domain name of the server from which you wish to restore" 8 60 2>$data
    sel=$?
    case $sel in
        0)
            friend_server_domain_name=$(<$data)
            if [ ${#friend_server_domain_name} -lt 2 ]; then
                return
            fi
            if [[ $friend_server_domain_name != *"."* ]]; then
                dialog --title $"Remote server domain name" \
                       --msgbox $"Invalid domain name" 6 40
                return
            fi
            restore_from_remote $friend_server_domain_name
            ;;
    esac
}
function ping_enable_disable {
    ping_str=$"\nDo you want to enable other systems to ping this machine?\n\nPing may be useful for diagnostic purposes, but for added security you may not want to enable it."
    enable_ping="no"
    dialog --title $"Enable Ping / ICMP" \
           --backtitle $"Freedombone Control Panel" \
           --defaultno \
           --yesno "$ping_str" 10 60
    sel=$?
    case $sel in
        0) enable_ping="yes";;
        255) return;;
    esac
    if [[ $enable_ping == "yes" ]]; then
        iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
        iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
        echo "0" >  /proc/sys/net/ipv4/icmp_echo_ignore_all
    else
        iptables -D INPUT -p icmp --icmp-type echo-request -j ACCEPT
        iptables -D OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
        echo "1" >  /proc/sys/net/ipv4/icmp_echo_ignore_all
    fi
}
function logging_on_off {
    logging="no"
    dialog --title $"Logging" \
           --backtitle $"Freedombone Control Panel" \
           --yesno $"\nDo you want to turn logging on?" 7 60
    sel=$?
    case $sel in
        0) logging="yes";;
        255) return;;
    esac
    clear
    echo ''
    echo $'This may take a few seconds. Please wait...'
    if [[ $logging == "no" ]]; then
        ${PROJECT_NAME}-logging off
    else
        ${PROJECT_NAME}-logging on
    fi
}
function restore_gpg_key {
    select_user
    if [ ! $SELECTED_USERNAME ]; then
        return
    fi
    restorestr=$"Restore GPG key for user"
    dialog --title "$restorestr $SELECTED_USERNAME" \
           --msgbox $"Plug in your USB keydrive" 6 40
    clear
    ${PROJECT_NAME}-recoverkey -u $SELECTED_USERNAME
    any_key
}
function security_settings {
    ${PROJECT_NAME}-sec
    any_key
}
function reset_tripwire {
  clear
  echo $'Resetting the Tripwire...'
  echo ' '
  echo '
' | reset-tripwire
  any_key
}
function hubzilla_renew_cert {
    dialog --title $"Renew SSL certificate" \
           --backtitle $"Freedombone Control Panel" \
           --yesno $"\nThis will renew a letsencrypt certificate. Select 'yes' to continue" 16 60
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    HUBZILLA_DOMAIN_NAME=$(cat $COMPLETION_FILE | grep "Hubzilla domain" | awk -F ':' '{print $2}')
    if [ ! -d /var/www/$HUBZILLA_DOMAIN_NAME/htdocs ]; then
       dialog --title $"Renew SSL certificate" \
              --msgbox $"Hubzilla install directory not found" 6 40
       return
    fi
    ${PROJECT_NAME}-renew-cert -h $HUBZILLA_DOMAIN_NAME -p 'letsencrypt'
    if [ ! "$?" = "0" ]; then
        any_key
    else
        dialog --title $"Renew SSL certificate" \
               --msgbox $"Hubzilla certificate has been renewed" 6 40
    fi
}
function hubzilla_channel_directory_server {
    if ! grep -q "Hubzilla domain" $COMPLETION_FILE; then
       dialog --title $"Hubzilla channel directory server" \
              --msgbox $"Hubzilla is not installed on this system" 6 40
       return
    fi
    HUBZILLA_DOMAIN_NAME=$(cat $COMPLETION_FILE | grep "Hubzilla domain" | awk -F ':' '{print $2}')
    if [ ! -d /var/www/$HUBZILLA_DOMAIN_NAME/htdocs ]; then
       dialog --title $"Hubzilla channel directory server" \
              --msgbox $"Hubzilla install directory not found" 6 40
       return
    fi
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --title $"Hubzilla channel directory server" \
           --backtitle $"Freedombone Control Panel" \
           --inputbox $"When you click on 'channel directory' this is where Hubzilla will obtain its list from" 8 60 2>$data
    sel=$?
    case $sel in
        0)
            hubzilla_domain_server=$(<$data)
            if [[ $hubzilla_domain_server != *"."* ]]; then
                return
            fi
            if [[ $hubzilla_domain_server != "https"* ]]; then
                dialog --title $"Hubzilla channel directory server" \
                       --msgbox $"Invalid domain - include the https://" 6 40
                return
            fi
            ./var/www/$HUBZILLA_DOMAIN_NAME/htdocs/util/config system directory_server $hubzilla_domain_server
            dialog --title $"Hubzilla channel directory server" \
                   --msgbox $"Domain channel directory server changed to $hubzilla_domain_server" 6 40
            ;;
    esac
}
function format_drive {
    drive=
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Format a USB drive (LUKS encrypted)" \
           --radiolist $"Choose a drive:" 12 70 5 \
           1 $"sda (Beaglebone Black)" off \
           2 $"sdb" off \
           3 $"sdc" off \
           4 $"sdd" off \
           5 $"Back to Backup and Restore menu" on 2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    case $(cat $data) in
        1) drive='sda';;
        2) drive='sdb';;
        3) drive='sdc';;
        4) drive='sdd';;
        5) return;;
    esac
    dialog --title $"Format USB drive" \
           --backtitle $"Freedombone Control Panel" \
           --defaultno \
           --yesno $"\nPlease confirm that you wish to format drive\n\n    ${drive}\n\nAll current data on the drive will be lost, and you will be prompted to give a password used to encrypt the drive.\n\nDANGER: If you screw up here and format the wrong drive it's your own fault!" 16 60
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    clear
    ${PROJECT_NAME}-format $drive
    any_key
}
function remove_backups {
    drive=
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Remove backups from a USB drive" \
           --radiolist $"Choose a drive:" 12 70 5 \
           1 $"sda (Beaglebone Black)" off \
           2 $"sdb" off \
           3 $"sdc" off \
           4 $"sdd" off \
           5 $"Back to Backup and Restore menu" on 2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    case $(cat $data) in
        1) drive='sda';;
        2) drive='sdb';;
        3) drive='sdc';;
        4) drive='sdd';;
        5) return;;
    esac
    dialog --title $"Remove backups from a USB drive" \
           --backtitle $"Freedombone Control Panel" \
           --defaultno \
           --yesno $"\nPlease confirm that you wish to remove backups from this drive\n\n    ${drive}\n\nYou will not be able to recover them afterwards." 12 60
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    clear
    ${PROJECT_NAME}-backup-local $drive remove
    any_key
}
function shut_down_system {
    dialog --title $"Power off the system" \
           --backtitle $"Freedombone Control Panel" \
           --defaultno \
           --yesno $"\nPlease confirm that you wish to power off the system.\n\nWARNING: to power on again you will need to have physical access to the hardware." 10 60
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    shutdown now
}
function restart_system {
    dialog --title $"Restart the system" \
           --backtitle $"Freedombone Control Panel" \
           --defaultno \
           --yesno $"\nPlease confirm that you wish to restart the system.\n\nWARNING: If you are using full disk encryption then you will need physical access to the hardware to type in the password" 10 60
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    reboot
}
function change_system_name {
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --title $"Change the name of this system" \
           --backtitle $"Freedombone Control Panel" \
           --inputbox $'Enter a new name for this system on your local network\n\nIt will appear as newname.local' 10 60 2>$data
    sel=$?
    case $sel in
        0) NEW_SYSTEM_NAME=$(<$data)
           if [ "$NEW_SYSTEM_NAME" ]; then
               if [ ${#NEW_SYSTEM_NAME} -gt 1 ]; then
                   sed -i "s|host-name=.*|host-name=$NEW_SYSTEM_NAME|g" /etc/avahi/avahi-daemon.conf
                   systemctl restart avahi-daemon
                   if grep -q "host-name=$NEW_SYSTEM_NAME" /etc/avahi/avahi-daemon.conf; then
                       dialog --title $"New local network name" \
                              --msgbox $"The name of this system on your local network was changed successfully" 6 70
                   fi
               fi
           fi
           ;;
    esac
}
function set_tls_time_source {
    TLS_DATE_SOURCE=$(cat /usr/bin/updatedate | grep "TIMESOURCE='" | awk -F '=' '{print $2}' | awk -F "'" '{print $2}')
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --title $"Set the TLS date/time source" \
           --backtitle $"Freedombone Control Panel" \
           --inputbox $"Enter a domain name to use as a TLS time source.\n\nFactors to consider when choosing a source are whether you wish that site to know that your system is 'alive' and also what might happen if an adversary were to try to mess with the date/time from that domain (i.e. how much blowback would there be)." 14 60 "$TLS_DATE_SOURCE" 2>$data
    sel=$?
    case $sel in
        0) NEW_TLS_DATE_SOURCE=$(<$data)
           if [[ $NEW_TLS_DATE_SOURCE == *"."* && $NEW_TLS_DATE_SOURCE != *'/'* ]]; then
               if [[ $NEW_TLS_DATE_SOURCE != "http"* ]]; then
                   sed -i "s|TIMESOURCE='.*|TIMESOURCE='${NEW_TLS_DATE_SOURCE}'|g" $UPDATE_DATE_SCRIPT
               else
                   dialog --title $"Invalid domain name" \
                          --msgbox $"Don't include the 'https'" 6 70
               fi
           else
               dialog --title $"Invalid domain name" \
                      --msgbox $"That doesn't look like a domain name" 6 70
           fi
           ;;
    esac
}
function set_static_IP {
    STATIC_IP='192.168.1.60'
    STATIC_GATEWAY='192.168.1.1'
    NEW_STATIC_IP=
    NEW_STATIC_GATEWAY=
    if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
        STATIC_IP=$(cat /etc/network/interfaces | grep "address " | awk -F ' ' '{print $2}' | head -n 1)
        STATIC_GATEWAY=$(cat /etc/network/interfaces | grep "gateway " | awk -F ' ' '{print $2}' | head -n 1)
    fi
    # get the IP for the box
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --title $"Set a static local IP address" \
           --backtitle $"Freedombone Control Panel" \
           --inputbox $"In order to forward incoming internet traffic to this system most internet routers need to know a static local IP address to send the data to.\n\n
Enter a static local IP address for this system.\n\nIt will typically be 192.168.1.x" 15 60 "$STATIC_IP" 2>$data
    sel=$?
    case $sel in
        0) NEW_STATIC_IP=$(<$data)
           if [[ "$NEW_STATIC_IP" != *"."* ]]; then
               return
           fi
           if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
               if [[ "$NEW_STATIC_IP" != "$STATIC_IP" ]]; then
                   sed -i "s|${STATIC_IP}|${NEW_STATIC_IP}|g" /etc/network/interfaces
               fi
           fi
           ;;
    esac
    # get the gateway
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --title $"Set the IP address of your internet router/modem" \
           --backtitle $"Freedombone Control Panel" \
           --inputbox $"Set the local IP address for your internet router or ADSL modem.\n\nIt will typically be 192.168.1.1, 192.168.1.254, or similar" 12 60 "$STATIC_GATEWAY" 2>$data
    sel=$?
    case $sel in
        0) NEW_STATIC_GATEWAY=$(<$data)
           if [[ "$NEW_STATIC_GATEWAY" != *"."* ]]; then
               return
           fi
           if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
               if [[ "$NEW_STATIC_GATEWAY" != "$STATIC_GATEWAY" ]]; then
                   sed -i "s|${STATIC_GATEWAY}|${NEW_STATIC_GATEWAY}|g" /etc/network/interfaces
               fi
               return
           fi
           ;;
    esac
    if ! grep -q 'iface eth0 inet static' /etc/network/interfaces; then
        if [ "$NEW_STATIC_GATEWAY" && "$NEW_STATIC_IP" ]; then
            echo '# This file describes the network interfaces available on your system' > /etc/network/interfaces
            echo '# and how to activate them. For more information, see interfaces(5).' >> /etc/network/interfaces
            echo '' >> /etc/network/interfaces
            echo '# The loopback network interface' >> /etc/network/interfaces
            echo 'auto lo' >> /etc/network/interfaces
            echo 'iface lo inet loopback' >> /etc/network/interfaces
            echo '' >> /etc/network/interfaces
            echo '# The primary network interface' >> /etc/network/interfaces
            echo 'auto eth0' >> /etc/network/interfaces
            echo 'iface eth0 inet static' >> /etc/network/interfaces
            echo "    address ${NEW_STATIC_IP}" >> /etc/network/interfaces
            echo '    netmask 255.255.255.0' >> /etc/network/interfaces
            echo "    gateway ${NEW_STATIC_GATEWAY}" >> /etc/network/interfaces
            echo "    dns-nameservers 213.73.91.35 85.214.20.141" >> /etc/network/interfaces
            echo '# Example to keep MAC address between reboots' >> /etc/network/interfaces
            echo '#hwaddress ether DE:AD:BE:EF:CA:FE' >> /etc/network/interfaces
            echo '' >> /etc/network/interfaces
            echo '# The secondary network interface' >> /etc/network/interfaces
            echo '#auto eth1' >> /etc/network/interfaces
            echo '#iface eth1 inet dhcp' >> /etc/network/interfaces
            echo '' >> /etc/network/interfaces
            echo '# WiFi Example' >> /etc/network/interfaces
            echo "#auto $WIFI_INTERFACE" >> /etc/network/interfaces
            echo "#iface $WIFI_INTERFACE inet dhcp" >> /etc/network/interfaces
            echo '#    wpa-ssid "essid"' >> /etc/network/interfaces
            echo '#    wpa-psk  "password"' >> /etc/network/interfaces
            echo '' >> /etc/network/interfaces
            echo '# Ethernet/RNDIS gadget (g_ether)' >> /etc/network/interfaces
            echo '# ... or on host side, usbnet and random hwaddr' >> /etc/network/interfaces
            echo '# Note on some boards, usb0 is automaticly setup with an init script' >> /etc/network/interfaces
            echo '#iface usb0 inet static' >> /etc/network/interfaces
            echo '#    address 192.168.7.2' >> /etc/network/interfaces
            echo '#    netmask 255.255.255.0' >> /etc/network/interfaces
            echo '#    network 192.168.7.0' >> /etc/network/interfaces
            echo '#    gateway 192.168.7.1' >> /etc/network/interfaces
        fi
    fi
}
function menu_backup_restore {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"Backup and Restore" \
               --radiolist $"Choose an operation:" 18 70 11 \
               1 $"Backup data to USB drive" off \
               2 $"Restore GPG key from USB keydrive" off \
               3 $"Restore data from USB drive" off \
               4 $"Configure remote backups" off \
               5 $"Restore from remote backup" off \
               6 $"Backup GPG key to USB (master keydrive)" off \
               7 $"Backup GPG key to USB (fragment keydrive)" off \
               8 $"Format a USB drive (LUKS encrypted)" off \
               9 $"Remove backups from a USB drive" off \
               10 $"Back to main menu" on 2> $data
        sel=$?
        case $sel in
            1) break;;
            255) break;;
        esac
        case $(cat $data) in
            1) backup_data;;
            2) restore_gpg_key;;
            3) restore_data;;
            4) configure_remote_backups;;
            5) restore_data_remote;;
            6) create_keydrive_master;;
            7) create_keydrive_fragment;;
            8) format_drive;;
            9) remove_backups;;
            10) break;;
        esac
    done
}
function menu_email {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"Email Filtering Rules" \
               --radiolist $"Choose an operation:" 13 70 6 \
               1 $"Add a user to a mailing list" off \
               2 $"Remove a user from a mailing list" off \
               3 $"Add an email rule" off \
               4 $"Block/Unblock an email address" off \
               5 $"Block/Unblock email with subject text" off \
               6 $"Back to main menu" on 2> $data
        sel=$?
        case $sel in
            1) break;;
            255) break;;
        esac
        case $(cat $data) in
            1) add_to_mailing_list;;
            2) remove_user_from_mailing_list;;
            3) email_rule;;
            4) block_unblock_email;;
            5) block_unblock_subject;;
            6) break;;
        esac
    done
}
function menu_users {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"Manage Users" \
               --radiolist $"Choose an operation:" 12 70 5 \
               1 $"Add a user" off \
               2 $"Delete a user" off \
               3 $"Change user password" off \
               4 $"Change user ssh public key" off \
               5 $"Back to main menu" on 2> $data
        sel=$?
        case $sel in
            1) break;;
            255) break;;
        esac
        case $(cat $data) in
            1) add_user;;
            2) delete_user;;
            3) change_password;;
            4) change_ssh_public_key;;
            5) break;;
        esac
    done
}
function menu_hubzilla {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"Hubzilla" \
               --radiolist $"Choose an operation:" 13 70 4 \
               1 $"Set channel directory server" off \
               2 $"Renew SSL certificate" off \
               3 $"Back to main menu" on 2> $data
        sel=$?
        case $sel in
            1) break;;
            255) break;;
        esac
        case $(cat $data) in
            1) hubzilla_channel_directory_server;;
            2) hubzilla_renew_cert;;
            3) break;;
        esac
    done
}
function menu_media {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"Media Menu" \
               --radiolist $"Choose an operation:" 13 70 3 \
               1 $"Attach a drive containing playable media" off \
               2 $"Remove a drive containing playable media" off \
               3 $"Exit" on 2> $data
        sel=$?
        case $sel in
            1) break;;
            255) break;;
        esac
        case $(cat $data) in
            1) remove-music
               attach-music;;
            2) remove-music;;
            3) break;;
        esac
    done
}
function menu_irc {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"IRC Menu" \
               --radiolist $"Choose an operation:" 14 70 4 \
               1 $"Set a password for all IRC users" off \
               2 $"Access via the onion address" off \
               3 $"Exit" on 2> $data
        sel=$?
        case $sel in
            1) break;;
            255) break;;
        esac
        case $(cat $data) in
            1) irc_set_global_password;;
            2) irc_via_onion;;
            3) break;;
        esac
    done
}
function menu_top_level {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"Control Panel" \
               --radiolist $"Choose an operation:" 26 70 19 \
               1 $"About this system" off \
               2 $"Backup and Restore" off \
               3 $"Reset Tripwire" off \
               4 $"Logging on/off" off \
               5 $"Ping enable/disable" off \
               6 $"Manage Users" off \
               7 $"Email Filtering Rules" off \
               8 $"Security Settings" off \
               9 $"Set the main repository (repo mirrors)" off \
               10 $"Hubzilla" off \
               11 $"Media menu" off \
               12 $"IRC menu" off \
               13 $"Change the name of this system" off \
               14 $"Set the TLS date/time source" off \
               15 $"Set a static local IP address" off \
               16 $"Check for updates" off \
               17 $"Power off the system" off \
               18 $"Restart the system" off \
               19 $"Exit" on 2> $data
        sel=$?
        case $sel in
            1) exit 1;;
            255) exit 1;;
        esac
        case $(cat $data) in
            1) show_about;;
            2) menu_backup_restore;;
            3) reset_tripwire;;
            4) logging_on_off;;
            5) ping_enable_disable;;
            6) menu_users;;
            7) menu_email;;
            8) security_settings;;
            9) set_main_repo;;
            10) menu_hubzilla;;
            11) menu_media;;
            12) menu_irc;;
            13) change_system_name;;
            14) set_tls_time_source;;
            15) set_static_IP;;
            16) check_for_updates;;
            17) shut_down_system;;
            18) restart_system;;
            19) break;;
        esac
    done
}
if [ ! -f $COMPLETION_FILE ]; then
    echo $'This command should only be run on an installed Freedombone system'
    exit 1
fi
ADMIN_USER=$(cat $COMPLETION_FILE | grep "Admin user" | awk -F ':' '{print $2}')
read_repo_servers
menu_top_level
clear
cat /etc/motd
exit 0
 |