#!/bin/bash # _____ _ _ # | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___ # | __| _| -_| -_| . | . | | . | . | | -_| # |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___| # # Freedom in the Cloud # # Install daemon for the web admin system # See also freedombone-utils-webadmin # # License # ======= # # Copyright (C) 2018-2019 Bob Mottram <bob@freedombone.net> # # 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}-installer export TEXTDOMAINDIR="/usr/share/locale" # for outgoing smtp relay source "/usr/share/${PROJECT_NAME}/base/${PROJECT_NAME}-base-email" SSH_PORT=2222 INSTALL_STATE_FIRST_BOOT=0 INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED=1 INSTALL_STATE_RUNNING_COMMAND=2 INSTALL_STATE_COMMAND_FAIL=3 INSTALL_STATE_COMMAND_SUCCESS=4 # Timeouts for various operations to ensure the system doesn't hang APP_INSTALL_TIMEOUT_SEC=3600 BACKUP_TIMEOUT_SEC=7200 FORMAT_TIMEOUT_SEC=600 # file containing new password IMAGE_PASSWORD_FILE=/root/login.txt # Stores a list of drives when the system was first installed. # This is used to detect drives later connected DRIVES_BASELINE_FILE=/root/.drives_baseline install_state=$INSTALL_STATE_FIRST_BOOT CONFIGURATION_FILE="/root/${PROJECT_NAME}.cfg" COMPLETION_FILE="/root/${PROJECT_NAME}-completed.txt" # file containing a list of removed apps REMOVED_APPS_FILE=/root/removed # name of the app currently being installed APP_BEING_INSTALLED= # contains the blocked users and domains FIREWALL_DOMAINS=/root/${PROJECT_NAME}-firewall-domains.cfg # contains words or phrases to be blocked MUTED_WORDS=/root/${PROJECT_NAME}-firewall-words.cfg local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" default_domain_file="$webadmin_install_dir/.default_domain.txt" scuttlebot_file="$webadmin_install_dir/.scuttlebot_invite.txt" email_proxy_file="$webadmin_install_dir/.emailproxy.txt" theme_file="$webadmin_install_dir/.theme.txt" translations_import_file="$webadmin_install_dir/.translations_import.txt" icecast_file="$webadmin_install_dir/.icecast.txt" koel_file="$webadmin_install_dir/.koel.txt" dlna_file="$webadmin_install_dir/.dlna.txt" datlinks_file="$webadmin_install_dir/.datlinks.txt" settings_updates_file="$webadmin_install_dir/.settingsupdates.txt" ssh_file="$webadmin_install_dir/.ssh.txt" smolrss_file="$webadmin_install_dir/.rssfeeds.txt" syncthing_file="$webadmin_install_dir/.syncthing.txt" appsettings_file="$webadmin_install_dir/.appsettings.txt" factoryreset_file="$webadmin_install_dir/.factoryreset.txt" upgrade_file="$webadmin_install_dir/.upgrade.txt" language_file="$webadmin_install_dir/.language.txt" system_monitor_file="$webadmin_install_dir/.system_monitor.txt" dynamic_dns_file="$webadmin_install_dir/.dynamicdns.txt" reset_file="$webadmin_install_dir/.reset.txt" shutdown_file="$webadmin_install_dir/.shutdown.txt" setup_file="$webadmin_install_dir/setup.txt" domain_file="$webadmin_install_dir/.temp_domain.txt" pending_removes="$webadmin_install_dir/pending_removes.txt" pending_installs="$webadmin_install_dir/pending_installs.txt" new_user_file="$webadmin_install_dir/.new_user.txt" remove_user_file="$webadmin_install_dir/.remove_user.txt" change_password_file="$webadmin_install_dir/changepassword.dat" install_state_file="/root/.install_state.txt" blocklist_file="$webadmin_install_dir/.blocklist.txt" muted_words_file="$webadmin_install_dir/.blocklistwords.txt" bridgeslist_file="$webadmin_install_dir/.bridgeslist.txt" INSTALL_DIR=/root/build webadmin_user='admin' webadmin_temp_password_file=/root/.temp_webadmin_password installer_script=/root/.fbone_installer.sh # Used to initiate automatic backups webadmin_prev_hour=99 # temporary backup and restore scripts factoryreset_script=/root/.webadmin_factory_reset.sh upgrade_script=/root/.webadmin_upgrade.sh backup_script=/root/.webadmin_backup.sh backup_keys_script=/root/.webadmin_backup_keys.sh restore_script=/root/.webadmin_restore.sh restore_keys_script=/root/.webadmin_restore_keys.sh format_script=/root/.webadmin_format.sh new_user_script=/root/.webadmin_new_user.sh remove_user_script=/root/.webadmin_remove_user.sh appsettings_script=/root/.webadmin_appsettings.sh # Files used to initiate backup or restore manually from the web UI backup_file="$webadmin_install_dir/.start_backup" backup_keys_file="$webadmin_install_dir/.start_backup_keys" restore_file="$webadmin_install_dir/.start_restore" restore_keys_file="$webadmin_install_dir/.start_restore_keys" format_file="$webadmin_install_dir/.start_format" # These files contain the percentage progress backup_progress_file=/root/.backup_progress.txt restore_progress_file=/root/.restore_progress.txt format_progress_file=/root/.format_progress.txt # whether an automatically scheduled backup is running running_auto_backup= backup_drive_mounted= USB_MOUNT=/mnt/usb ICECAST_PORT=8005 ICECAST_DIR=/icestream ICECAST_JINGLES=/jingles liquidsoap_script=/etc/liquidsoapuser/radio.liq webadmin_ipv4_address= webadmin_monitor_ip_ctr=1 function homepage_create_qr_code { webadmin_onion_domain="$1" if [ ! -f /usr/local/bin/myqr ]; then echo -n "http://${webadmin_onion_domain}/home" | qrencode -t PNG -o "$homepage_install_dir/images/homepage_qrcode.png" else myqr "http://${webadmin_onion_domain}/home" -p "/root/${PROJECT_NAME}/img/onion.png" -c -v 8 -n "$homepage_install_dir/images/homepage_qrcode.png" fi } function web_create_homepage { homepage_install_dir="/var/www/${local_hostname}/htdocs/home" homepage_filename="$homepage_install_dir/index.html" homepage_about_filename="$homepage_install_dir/about.html" homepage_template_filename="$webadmin_install_dir/homepage_template.html" icons_dir="$homepage_install_dir/icons" if [ ! -d "$homepage_install_dir" ]; then mkdir -p "$homepage_install_dir" fi if [ ! -d "$icons_dir" ]; then mkdir -p "$icons_dir" fi # NOTE: Here we don't use the icons from the admin directory # because that is password controlled. So that any user on the system # can use the homepage the icons are copied over to the home directory # copy the icons cp -r "$webadmin_install_dir/icons"/*.png "$icons_dir" # copy the logo if [ ! -d "$homepage_install_dir/images" ]; then mkdir -p "$homepage_install_dir/images" fi cp "$webadmin_install_dir/images/logo.png" "$homepage_install_dir/images" # copy the script used for search cp "$webadmin_install_dir/search.php" "$homepage_install_dir" if [ ! -f "$homepage_template_filename" ]; then return fi cp "$homepage_template_filename" "$homepage_filename" # copy the about screen for homepage cp "$webadmin_install_dir/homepage_about.html" "$homepage_about_filename" # show onion address for homepage webadmin_onion_domain=$(cat /var/lib/tor/hidden_service_webadmin/hostname) sed -i "s|WEBADMINONIONADDRESS|${webadmin_onion_domain}|g" "$homepage_about_filename" homepage_create_qr_code "$webadmin_onion_domain" } function get_external_ipv4_address { ipv4_result=$(curl -s ipinfo.io/ip) if [[ "$ipv4_result" != *'<'* ]]; then echo "$ipv4_result" else echo '' fi } function web_admin_background_color { if ! grep -q 'WEBADMIN_BACKGROUND_COLOR=' "/root/${PROJECT_NAME}.cfg"; then echo 'WEBADMIN_BACKGROUND_COLOR=white' >> "/root/${PROJECT_NAME}.cfg" fi if ! grep -q 'WEBADMIN_FOREGROUND_COLOR=' "/root/${PROJECT_NAME}.cfg"; then echo 'WEBADMIN_FOREGROUND_COLOR=black' >> "/root/${PROJECT_NAME}.cfg" fi bg_color=$(grep "WEBADMIN_BACKGROUND_COLOR=" "/root/${PROJECT_NAME}.cfg" | awk -F '=' '{print $2}') fg_color=$(grep "WEBADMIN_FOREGROUND_COLOR=" "/root/${PROJECT_NAME}.cfg" | awk -F '=' '{print $2}') local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local for webfile in "/var/www/${local_hostname}/htdocs/admin"/*.html; do if ! grep -q "background-color: ${bg_color};" "$webfile"; then sed -i "0,/background-color:.*/s//background-color: ${bg_color};/" "$webfile" sed -i "0,/ color:.*/s// color: ${fg_color};/" "$webfile" fi sed -i "s|color: blue|color: ${fg_color}|g" "$webfile" sed -i "s|color: darkblue|color: ${fg_color}|g" "$webfile" done # colors of the border around app categories apps_border_light=cfdde7 apps_border_dark=1f5177 search_background_light=5499ca search_background_dark=f9f3f3 search_background_light2=fdfdfd search_background_dark2=144163 # change colors on home screen sed -i "0,/background-color:.*/s//background-color: ${bg_color};/" "/var/www/${local_hostname}/htdocs/home/index.html" sed -i "0,/ color:.*/s// color: ${fg_color};/" "/var/www/${local_hostname}/htdocs/home/index.html" # change the search background if [[ "$bg_color" == 'white' ]]; then cp "/root/${PROJECT_NAME}/img/backgrounds/searx_light.png" "/etc/searx/searx/static/themes/courgette/img/bg-body-index.jpg" sed -i "s|$search_background_dark|$search_background_light|g" "/var/www/${local_hostname}/htdocs/admin/index.html" sed -i "s|$search_background_dark2|$search_background_light2|g" "/var/www/${local_hostname}/htdocs/admin/index.html" sed -i "s|$search_background_dark|$search_background_light|g" "/var/www/${local_hostname}/htdocs/home/index.html" sed -i "s|$search_background_dark2|$search_background_light2|g" "/var/www/${local_hostname}/htdocs/home/index.html" sed -i "s|$apps_border_dark|$apps_border_light|g" "/var/www/${local_hostname}/htdocs/admin/apps.html" sed -i "s|$apps_border_dark|$apps_border_light|g" "/var/www/${local_hostname}/htdocs/admin/apps_add.html" else cp "/root/${PROJECT_NAME}/img/backgrounds/searx_dark.png" "/etc/searx/searx/static/themes/courgette/img/bg-body-index.jpg" sed -i "s|$search_background_light|$search_background_dark|g" "/var/www/${local_hostname}/htdocs/admin/index.html" sed -i "s|$search_background_light2|$search_background_dark2|g" "/var/www/${local_hostname}/htdocs/admin/index.html" sed -i "s|$search_background_light|$search_background_dark|g" "/var/www/${local_hostname}/htdocs/home/index.html" sed -i "s|$search_background_light2|$search_background_dark2|g" "/var/www/${local_hostname}/htdocs/home/index.html" sed -i "s|$apps_border_light|$apps_border_dark|g" "/var/www/${local_hostname}/htdocs/admin/apps.html" sed -i "s|$apps_border_light|$apps_border_dark|g" "/var/www/${local_hostname}/htdocs/admin/apps_add.html" fi # change webmail theme if [ -f "/var/www/${local_hostname}/htdocs/mail/config/config.php" ]; then if [[ "$bg_color" == 'white' ]]; then sed -i 's|theme_default.*|theme_default = 54;|g' "/var/www/${local_hostname}/htdocs/mail/config/config.php" else sed -i 's|theme_default.*|theme_default = 55;|g' "/var/www/${local_hostname}/htdocs/mail/config/config.php" fi # remove the chosen theme parameter for filename in /var/local/squirrelmail/data/*.pref; do if grep -q 'chosen_theme' "$filename"; then sed -i '/chosen_theme/d' "$filename" fi done fi } function web_admin_create_app_descriptions { # this obtains the descriptions from each app and puts # them into a file which can then be used for translations FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*" app_descriptions_file="$webadmin_install_dir/app_descriptions.txt" if [ -f "$app_descriptions_file" ]; then rm "$app_descriptions_file" fi touch "$app_descriptions_file" for filename in $FILES do app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}') app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}') if grep -q "${app_name_upper}_SHORT_DESCRIPTION=" "${filename}"; then app_short_description=$(grep "${app_name_upper}_SHORT_DESCRIPTION=" "${filename}" | head -n 1 | awk -F '=' '{print $2}' | sed 's/\$//g' | sed 's/"//g' | sed "s/'//g") if [ "$app_short_description" ]; then if ! grep -Fxq "$app_short_description" "$app_descriptions_file"; then echo "$app_short_description" >> "$app_descriptions_file" fi fi fi if grep -q "${app_name_upper}_DESCRIPTION=" "${filename}"; then app_description=$(grep "${app_name_upper}_DESCRIPTION=" "${filename}" | head -n 1 | awk -F '=' '{print $2}' | sed 's/\$//g' | sed 's/"//g' | sed "s/'//g") if [ "$app_description" ]; then if ! grep -Fxq "$app_description" "$app_descriptions_file"; then echo "$app_description" >> "$app_descriptions_file" fi fi fi done if [ -f "$app_descriptions_file" ]; then chown www-data:www-data "$app_descriptions_file" fi } function web_admin_translate_text { text="$1" DEFAULT_LANGUAGE=$(grep "DEFAULT_LANGUAGE=" "/root/${PROJECT_NAME}.cfg" | awk -F '=' '{print $2}') if [[ "$DEFAULT_LANGUAGE" == "en_GB"* ]]; then echo "$text" return fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local translations_file="/var/www/${local_hostname}/htdocs/admin/translations/${DEFAULT_LANGUAGE}.txt" if [ -f "$translations_file" ]; then if grep -q "${text}|" "$translations_file"; then grep "${text}|" "$translations_file" | head -n 1 | awk -F '|' '{print $2}' return fi fi echo "$text" } function web_admin_translate { if ! grep -q 'DEFAULT_LANGUAGE=' "$CONFIGURATION_FILE"; then return fi language=$(grep 'DEFAULT_LANGUAGE=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [ ! "$language" ]; then return fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" webadmin_homepage_dir="/var/www/${local_hostname}/htdocs/home" translations_file="$webadmin_install_dir/translations/${language}.txt" if [ ! -f "$translations_file" ]; then return fi declare -a translations_array readarray translations_array < "$translations_file" echo "Starting translations" i=0 while (( ${#translations_array[@]} > i )); do translated_text= english_text=$(echo "${translations_array[i]}" | awk -F '|' '{print $1}') translated_text=$(echo "${translations_array[i]}" | awk -F '|' '{print $2}') if [ "$translated_text" ]; then # get the files containing this text # shellcheck disable=SC2207 webfiles=($(grep -l ">$english_text<" "$webadmin_install_dir"/*.html)) # translate each file j=0 while (( ${#webfiles[@]} > j )); do sed -i "/translate=\"yes\"/s|>$english_text<|>$translated_text<|g" "${webfiles[j]}" j=$((j+1)) done # get the files containing this button text # shellcheck disable=SC2207 webfiles=($(grep -l "value=\"$english_text\"" "$webadmin_install_dir"/*.html)) # translate each file j=0 while (( ${#webfiles[@]} > j )); do sed -i "/translate=\"yes\"/s|value=\"$english_text\"|value=\"$translated_text\"|g" "${webfiles[j]}" j=$((j+1)) done # get the alt text # shellcheck disable=SC2207 webfiles=($(grep -l " alt=\"$english_text\"" "$webadmin_install_dir"/*.html)) # translate each file j=0 while (( ${#webfiles[@]} > j )); do sed -i "s| alt=\"$english_text\"| alt=\"$translated_text\"|g" "${webfiles[j]}" j=$((j+1)) done # get titles # shellcheck disable=SC2207 webfiles=($(grep -l " title=\"$english_text\">" "$webadmin_install_dir"/*.html)) # translate each file j=0 while (( ${#webfiles[@]} > j )); do sed -i "s| title=\"$english_text\">| title=\"$translated_text\">|g" "${webfiles[j]}" j=$((j+1)) done # homepage ----------------------------------------------------------------------------- # shellcheck disable=SC2207 webfiles=($(grep -l ">$english_text<" "$webadmin_homepage_dir"/*.html)) # translate each file j=0 while (( ${#webfiles[@]} > j )); do sed -i "/translate=\"yes\"/s|>$english_text<|>$translated_text<|g" "${webfiles[j]}" j=$((j+1)) done # shellcheck disable=SC2207 webfiles=($(grep -l "value=\"$english_text\"" "$webadmin_homepage_dir"/*.html)) # translate each file j=0 while (( ${#webfiles[@]} > j )); do sed -i "/translate=\"yes\"/s|value=\"$english_text\"|value=\"$translated_text\"|g" "${webfiles[j]}" j=$((j+1)) done # shellcheck disable=SC2207 webfiles=($(grep -l " alt=\"$english_text\"" "$webadmin_homepage_dir"/*.html)) # translate each file j=0 while (( ${#webfiles[@]} > j )); do sed -i "s| alt=\"$english_text\"| alt=\"$translated_text\"|g" "${webfiles[j]}" j=$((j+1)) done fi i=$((i+1)) echo -n '.' done echo '' echo "Changing lang headers" langstr="${language:0:2}" for filename in "$webadmin_install_dir"/*.html; do sed -i 's|"yes" lang="en">||g' "$filename" done for filename in "$webadmin_install_dir"/*.html; do sed -i "s|<html>|<html lang=\"$langstr\">|g" "$filename" sed -i "s|<html lang=\"en\">|<html lang=\"$langstr\">|g" "$filename" done chown www-data:www-data "$webadmin_install_dir"/*.html echo "Translations complete" } function backup_mount_drive { backup_drive_mounted= if [ "$1" ]; then if [[ "$1" == "/dev/"* ]]; then USB_DRIVE="$1" else USB_DRIVE=/dev/${1}1 fi fi # check that the backup destination is available if [ ! -b "$USB_DRIVE" ]; then return fi # unmount if already mounted umount -f "$USB_MOUNT" if [ ! -d "$USB_MOUNT" ]; then mkdir "$USB_MOUNT" fi if [ -f /dev/mapper/encrypted_usb ]; then rm -rf /dev/mapper/encrypted_usb fi cryptsetup close encrypted_usb if ! mount "$USB_DRIVE" "$USB_MOUNT"; then rm -rf "$USB_MOUNT" return fi backup_drive_mounted=1 } function backup_unmount_drive { if ! umount "$USB_MOUNT"; then echo $"Unable to unmount the drive." rm -rf "$USB_MOUNT" return fi rm -rf "$USB_MOUNT" if [[ "$USB_DRIVE" == /dev/mapper/encrypted_usb ]]; then echo $"Unmount encrypted USB" cryptsetup close encrypted_usb fi if [ -f /dev/mapper/encrypted_usb ]; then rm -rf /dev/mapper/encrypted_usb fi backup_drive_mounted= } function detect_connected_drives { if [ ! -f $DRIVES_BASELINE_FILE ]; then # shellcheck disable=SC2012 ls -gA /dev/sd* | awk -F '/dev/' '{print $2}' > $DRIVES_BASELINE_FILE return fi # shellcheck disable=SC2012 ls -gA /dev/sd* | awk -F '/dev/' '{print $2}' > /tmp/.drives_current diff /tmp/.drives_current ${DRIVES_BASELINE_FILE} | awk -F '< ' '{print $2}' | sed '/^$/d' | sed 's/[0-9]*//g' | uniq | head -n 1 } function app_not_on_onion_only { app_name="$1" if [[ "$ONION_ONLY" != 'no' ]]; then if grep -q "NOT_ON_ONION=1" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"; then echo "0" return fi fi echo "1" } function app_not_on_arm { app_name="$1" if grep -q "NOT_ON_ARM=1" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"; then archtype=$(uname -m) if [[ "$archtype" == 'arm'* ]]; then echo "0" return fi fi echo "1" } function app_not_in_webadmin { app_name="$1" if grep -q "NOT_IN_WEBADMIN=1" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"; then echo "0" return fi echo "1" } function enough_ram_for_app { app_name="$1" if ! grep -q "MINIMUM_RAM_MB=" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"; then echo "0" return fi minimum_ram_MB=$(grep "MINIMUM_RAM_MB=" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" | head -n 1 | awk -F '=' '{print $2}') minimum_ram_bytes=$((minimum_ram_MB * 1024)) ram_available=$(grep MemTotal /proc/meminfo | awk '{print $2}') if [ "$ram_available" -lt "$minimum_ram_bytes" ]; then echo "1" return fi echo "0" } function webadmin_update_version { local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/about.html" ]; then VERSION=$(grep "VERSION=" "/usr/local/bin/${PROJECT_NAME}-vars" | grep -v DEBIAN | awk -F '"' '{print $2}') sed -i "s|\"versiontext\".*|\"versiontext\">$VERSION</p>|g" "$webadmin_install_dir/about.html" fi } function web_admin_onion_only { # In onion only mode domain names or ddns codes # don't need to be provided if ! grep -q 'ONION_ONLY=' "$CONFIGURATION_FILE"; then return fi ONION_ONLY=$(grep 'ONION_ONLY=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [ ! "$ONION_ONLY" ]; then ONION_ONLY='no' fi if [[ "$ONION_ONLY" == 'no' ]]; then return fi # shellcheck disable=SC2154 sed -i '/freedns_code/d' "$webadmin_install_dir/app_add_template.html" # shellcheck disable=SC2154 sed -i '/freedns_code/d' "$webadmin_install_dir/add_app_confirm_template.html" sed -i '/install_domain/d' "$webadmin_install_dir/app_add_template.html" sed -i '/install_domain/d' "$webadmin_install_dir/add_app_confirm_template.html" sed -i 's|onion_only=false;|onion_only=true;|g' "$webadmin_install_dir/installapp.php" sed -i 's|onion_only=false;|onion_only=true;|g' "$webadmin_install_dir/installappconfirm.php" sed -i 's|setup_domain.html|setup_installing.html|g' "$webadmin_install_dir/setupconfirm.php" } function get_app_categories { APP_CATEGORY=() APP_CATEGORY+=("chat") APP_CATEGORY+=("media") APP_CATEGORY+=("office") APP_CATEGORY+=("social") APP_CATEGORY+=("sync") APP_CATEGORY+=("publishing") APP_CATEGORY+=("other") } function web_admin_create_add_apps_category { # number of apps added add_apps_ctr=0 # This counter is used to enforce 4 icon rows available_apps_ctr=0 # Index within the array of all apps app_index=0 # shellcheck disable=SC2086 category_str="$(tr '[:lower:]' '[:upper:]' <<< ${category:0:1})${category:1}" translated_category=$(web_admin_translate_text "$category_str") apps_header_str="<fieldset class=\"field_set\"><legend translate=\"yes\" class=\"category\">$translated_category</legend>" echo " $apps_header_str" >> "$appslist_add_filename" for filename in $FILES do app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}') if [[ $(enough_ram_for_app "$app_name") == "0" ]]; then if [[ $(app_not_on_onion_only "$app_name") != "0" ]]; then if [[ $(app_not_on_arm "$app_name") != "0" ]]; then if [[ $(app_not_in_webadmin "$app_name") != "0" ]]; then app_is_installed= # check if the app is pending installation app_pending_install= if [ -f "$pending_installs" ]; then if grep -q "install_${app_name}" "$pending_installs"; then app_is_installed=1 app_pending_install=1 fi fi if [ ! $app_is_installed ]; then app_filename="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" if [ -f "$app_filename" ]; then # does this app have a category? if ! grep -q 'APP_CATEGORY=' "$app_filename"; then if [[ "$category" != 'other' ]]; then app_index=$((app_index+1)) continue fi fi # Does this app belong in the current category? if ! grep -q "APP_CATEGORY=$category" "$app_filename"; then app_index=$((app_index+1)) continue fi if grep -q "VARIANTS=''" "$app_filename"; then continue fi if grep -q 'VARIANTS=""' "$app_filename"; then continue fi # get the icon for the app icon_filename="/usr/share/${PROJECT_NAME}/android-app/${app_name}.png" if [ -f "$icon_filename" ]; then cp "$icon_filename" "$webadmin_install_dir/icons/${app_name}.png" else continue fi app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}') DESCRIPTION= if ! grep -q "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then continue fi if grep -q "#${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then continue fi SHORT_DESCRIPTION="$(grep "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')" translated_short_description=$(web_admin_translate_text "$SHORT_DESCRIPTION") SHORT_DESCRIPTION="$translated_short_description" app_title="${SHORT_DESCRIPTION}" if grep -q "${app_name_upper}_DESCRIPTION=" "$app_filename"; then DESCRIPTION="$(grep "${app_name_upper}_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')" translated_description=$(web_admin_translate_text "$DESCRIPTION") DESCRIPTION="$translated_description" app_title="${DESCRIPTION}" fi if [ $available_apps_ctr -eq 0 ]; then echo ' <div class="row">' >> "$appslist_add_filename" fi filename_app="$webadmin_install_dir/app_${app_name}.html" if [ -f "$filename_app" ]; then rm "$filename_app" fi filename_app="$webadmin_install_dir/app_add_${app_name}.html" if [ ! $app_pending_install ]; then { echo ' <div class="column">'; echo ' <div>'; echo " <a href=\"app_add_${app_name}.html\" title=\"${app_title}\">"; echo " <img src=\"icons/${app_name}.png\" style=\"width:40%\">"; echo " <center>${app_name}</center>"; echo ' </a>'; echo ' </div>'; echo ' </div>'; } >> "$appslist_add_filename" else { echo ' <div class="column">'; echo ' <div>'; echo " <img src=\"icons/${app_name}.png\" style=\"width:40%\">"; echo " <center class=\"installing\">${app_name}</center>"; echo ' </div>'; echo ' </div>'; } >> "$appslist_add_filename" fi cp "$app_add_template_filename" "$filename_app" # Replace app variables sed -i "s|HOSTNAME|$(hostname)|g" "$filename_app" sed -i "s|APPNAME|${app_name}|g" "$filename_app" sed -i "s|APPDESCRIPTION|${DESCRIPTION}|g" "$filename_app" app_add_remove_domain= if [[ "$ONION_ONLY" != 'no' ]]; then app_add_remove_domain=1 fi if grep -q 'SHOW_DOMAIN_IN_WEBADMIN=0' "$filename"; then app_add_remove_domain=1 sed -i '/freedns_code/d' "$filename_app" sed -i 's|"no_domain".*|"no_domain" value="1">|g' "$filename_app" fi # remove domain if necessary if [ $app_add_remove_domain ]; then if grep -q 'install_domain' "$filename_app"; then sed -i '/install_domain/d' "$filename_app" fi sed -i "/installappconfirm.php/a <input type=\"hidden\" name=\"install_domain\" value=\"${app_name}.$(hostname)\">" "$filename_app" fi if grep -q 'freedns_code' "$filename_app"; then sed -i '/freedns_code/d' "$filename_app" fi available_apps_ctr=$((available_apps_ctr+1)) add_apps_ctr=$((add_apps_ctr+1)) # four columns per row if [ $available_apps_ctr -eq 4 ]; then echo ' </div>' >> "$appslist_add_filename" available_apps_ctr=0 fi fi fi fi fi fi fi done if [ ${available_apps_ctr} -gt 0 ]; then # Complete the rest of the four column row # shellcheck disable=SC2034 for i in $(seq ${available_apps_ctr} 3) do { echo ' <div class="column">'; echo ' <div>'; echo ' </div>'; echo ' </div>'; } >> "$appslist_add_filename" done echo ' </div>' >> "$appslist_add_filename" fi if [ ${add_apps_ctr} -gt 0 ]; then echo ' </fieldset>' >> "$appslist_add_filename" else # remove the header for this category sed -i "/>$translated_category</d" "$appslist_add_filename" fi } function web_admin_create_add_apps { if grep -q 'ONION_ONLY=' "$CONFIGURATION_FILE"; then ONION_ONLY=$(grep 'ONION_ONLY=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') else ONION_ONLY='no' fi appslist_add_filename="$webadmin_install_dir/apps_add.html" apps_add_template_filename="$webadmin_install_dir/apps_add_template.html" pending_installs="$webadmin_install_dir/pending_installs.txt" icons_dir="$webadmin_install_dir/icons" app_add_template_filename="$webadmin_install_dir/app_add_template.html" FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*" if [ ! -d "$icons_dir" ]; then mkdir -p "$icons_dir" fi if [ ! -f "$apps_add_template_filename" ]; then return fi cp "$apps_add_template_filename" "$appslist_add_filename" sed -i '/<\/div>/d' "$appslist_add_filename" sed -i '/<\/body>/d' "$appslist_add_filename" sed -i '/<\/html>/d' "$appslist_add_filename" get_app_categories # shellcheck disable=SC2068,SC2034 for category in ${APP_CATEGORY[@]} do web_admin_create_add_apps_category done { echo ' </div>'; echo ' <br><br>'; echo ' </body>'; echo '</html>'; } >> "$appslist_add_filename" chown -R www-data:www-data "$webadmin_install_dir" } function web_admin_create_installed_apps { appslist_filename="$webadmin_install_dir/apps.html" appslist_template_filename="$webadmin_install_dir/apps_template.html" icons_dir="$webadmin_install_dir/icons" pending_removes="$webadmin_install_dir/pending_removes.txt" if [ ! -d "$icons_dir" ]; then mkdir -p "$icons_dir" fi if [ ! -f "$appslist_template_filename" ]; then return fi cp "$appslist_template_filename" "$appslist_filename" sed -i '/<\/div> <!-- header -->/d' "$appslist_filename" sed -i '/<\/body>/d' "$appslist_filename" sed -i '/<\/html>/d' "$appslist_filename" installed_apps_ctr=0 # Complete the rest of the four column row # shellcheck disable=SC2034 for i in $(seq ${installed_apps_ctr} 3) do { echo ' <div class="column">'; echo ' <div>'; echo ' </div>'; echo ' </div>'; } >> "$appslist_filename" done { echo ' </div>'; echo ' </body>'; echo '</html>'; } >> "$appslist_filename" chown -R www-data:www-data "$webadmin_install_dir" } function web_admin_create_users { if [ ! -d "/home/$webadmin_user" ]; then return fi users_file="$webadmin_install_dir/users.html" cp "$webadmin_install_dir"/users_template.html "$users_file" sed -i '/users list/,/end of users/d' "$users_file" sed -i '/<\/body>/d' "$users_file" sed -i '/<\/html>/d' "$users_file" echo " <div class=\"row\">" >> "$users_file" echo " <div class=\"column\">" >> "$users_file" rm "$webadmin_install_dir/userprofile_"* USERNAME="$webadmin_user" userfile="$webadmin_install_dir/userprofile_${USERNAME}.html" useremail=${USERNAME}@${HOSTNAME} GPG_ID=$(su -c "gpg --list-keys '$useremail'" - "$USERNAME" | sed -n '2p' | sed 's/^[ \t]*//') if [ -f "/home/$USERNAME/.gnupg/gpg.conf" ]; then if grep -q "default-key" "/home/$USERNAME/.gnupg/gpg.conf"; then default_gpg_key=$(grep "default-key" "/home/$USERNAME/.gnupg/gpg.conf") if [[ "$default_gpg_key" != *'#'* ]]; then default_gpg_key=$(grep "default-key" "/home/$USERNAME/.gnupg/gpg.conf" | awk -F ' ' '{print $2}') if [ ${#default_gpg_key} -gt 3 ]; then GPG_ID=$(su -c "gpg --list-keys '$default_gpg_key'" - "$USERNAME" | sed -n '2p' | sed 's/^[ \t]*//') fi fi fi fi #pubkey_qrcode="$webadmin_install_dir/images/userprofile_${USERNAME}.png" #su -c "gpg --armor --export \"$GPG_ID\"" - "$USERNAME" | qrencode -t PNG -o "$pubkey_qrcode" { echo ' <div class="chip">'; echo " <a href=\"userprofile_${USERNAME}.html\" title=\"${USERNAME}\">"; echo ' <img src="images/user_admin.png" alt="Person" width="96" height="96">'; echo " $USERNAME"; echo ' </a>'; echo ' </div>'; } >> "$users_file" cp "$webadmin_install_dir"/userprofile.html "$userfile" sed -i "s|USERNAME|${USERNAME}|g" "$userfile" if [[ "$USERNAME" == "$webadmin_user" ]]; then sed -i "s|USERTYPE|Admin|g" "$userfile" sed -i '/remove user button/,/end of remove/d' "$userfile" else sed -i "s|USERTYPE|User|g" "$userfile" fi if [[ "$useremail" != *'.onion' ]]; then useronionemail=${USERNAME}@$(cat /var/lib/tor/hidden_service_email/hostname) sed -i "s|USEREMAIL|${useremail}<br><br>${useronionemail}|g" "$userfile" else sed -i "s|USEREMAIL|${useremail}|g" "$userfile" fi sed -i "s|USERGPG|${GPG_ID}|g" "$userfile" chown www-data:www-data "$userfile" #chown www-data:www-data "$pubkey_qrcode" translated_add_user=$(web_admin_translate_text "Add a new member") { echo ' <div class="chip">'; echo " <a href=\"new_user.html\" title=\"${translated_add_user}\">"; echo ' <img src="images/user.png" alt="Person" width="96" height="96">'; echo ' <div class="adduser">+</div>'; echo ' </a>'; echo ' </div>'; echo ' </div>'; echo ' </div>'; echo ' </body>'; echo '</html>'; } >> "$users_file" chown www-data:www-data "$users_file" } function wait_for_enough_entropy { # Wait indefinitely until enough entropy is available to # generate the webadmin login password while true do ENTROPY=$(cat /proc/sys/kernel/random/entropy_avail) # shellcheck disable=SC2086 if [ $ENTROPY -gt 500 ]; then break fi sleep 2 done } function create_random_string { wait_for_enough_entropy openssl rand -base64 32 | tr -dc A-Za-z0-9 | head -c "${1}" ; echo -n '' } function web_admin_create_user { username="$1" password="$2" if [ ! "$username" ]; then return fi chmod 600 /etc/shadow chmod 600 /etc/gshadow if [ ! -d "/home/$username" ]; then useradd -m -p "$password" -s /bin/bash "$username" groupadd "$username" fi echo -n "${username}:${password}" | /usr/sbin/chpasswd chmod 0000 /etc/shadow chmod 0000 /etc/gshadow } function web_admin_setup_login { if [ $install_state -ne $INSTALL_STATE_FIRST_BOOT ]; then return fi # if an nginx password file has not been created for web admin if [ -f /etc/nginx/.webadminpasswd ]; then return fi # remove master password for the password manager if [ -f /root/.passwords/root/master ]; then rm /root/.passwords/root/master fi # remove detected drives file used by backup system if [ -f $DRIVES_BASELINE_FILE ]; then rm $DRIVES_BASELINE_FILE fi # this file indicates that the setup screen is active # and gets removed by freedombone-installer if [ ! -f "$webadmin_install_dir/.setupscreenactive" ]; then touch "$webadmin_install_dir/.setupscreenactive" fi if [ ! -f $webadmin_temp_password_file ]; then wait_for_enough_entropy if [ -f /usr/share/dict/words ]; then webadmin_password=$(diceware) if [ ! "$webadmin_password" ]; then webadmin_password="$(openssl rand -base64 32 | tr -dc A-Za-z0-9 | head -c 10 ; echo -n '')" fi else webadmin_password="$(openssl rand -base64 32 | tr -dc A-Za-z0-9 | head -c 10 ; echo -n '')" fi echo -n "$webadmin_password" > $webadmin_temp_password_file else webadmin_password=$(cat $webadmin_temp_password_file) fi web_admin_create_user "$webadmin_user" "$webadmin_password" # ensure that username is set if ! grep "MY_USERNAME=$webadmin_user" "$CONFIGURATION_FILE"; then echo "MY_USERNAME=$webadmin_user" >> "$CONFIGURATION_FILE" else sed -i "s|MY_USERNAME=.*|MY_USERNAME=$webadmin_user|g" "$CONFIGURATION_FILE" fi # create a password for users if [ ! -f /etc/nginx/.webadminpasswd ]; then touch /etc/nginx/.webadminpasswd fi # create a password file used by nginx echo -n "$webadmin_password" | htpasswd -i -s -c /etc/nginx/.webadminpasswd "$webadmin_user" if ! grep -q "${webadmin_user}:" /etc/nginx/.webadminpasswd; then echo $"/etc/nginx/.webadminpasswd password not created for $webadmin_user" if [ -f /etc/nginx/.webadminpasswd ]; then rm /etc/nginx/.webadminpasswd fi return fi # create a setup page with the initial password inserted # and copy it to the index cp "$webadmin_install_dir"/setup.html "$webadmin_install_dir"/setup.prev cp "$webadmin_install_dir"/setup_confirm_template.html "$webadmin_install_dir"/setup_confirm.html sed -i "s|WEBADMINPASSWORD|${webadmin_password}|g" "$webadmin_install_dir/setup.prev" sed -i "s|WEBADMINPASSWORD|${webadmin_password}|g" "$webadmin_install_dir/setup_confirm.html" cp "$webadmin_install_dir"/setup.prev "$webadmin_install_dir"/index.html # if initial setup has not yet happened then create # a password file if ! grep -q 'install_final' "$COMPLETION_FILE"; then echo -n "$webadmin_password" > ${IMAGE_PASSWORD_FILE} fi web_admin_background_color web_admin_create_app_descriptions web_admin_translate echo -n "$INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED" > "$install_state_file" install_state=$INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED } function enable_webadmin_login { # switch on nginx authentication for freedombone.local if grep -q "#auth_basic" "/etc/nginx/sites-available/${local_hostname}"; then sed -i 's|#auth_basic|auth_basic|g' "/etc/nginx/sites-available/${local_hostname}" fi } function remove_initial_setup_page { if [ -f "$webadmin_install_dir/index.prev" ]; then # Replace the installing screen with the main index page when done # It should reload by itself if [ -f "$webadmin_install_dir/setup_installing.html" ]; then cp "$webadmin_install_dir/EN/index.html" "$webadmin_install_dir/setup_installing.html" fi # Replace the setup confirm screen with the main index if [ -f "$webadmin_install_dir/setup_confirm.html" ]; then cp "$webadmin_install_dir/EN/index.html" "$webadmin_install_dir/setup_confirm.html" fi # Replace the setup domain screen with the main index if [ -f "$webadmin_install_dir/setup_domain.html" ]; then cp "$webadmin_install_dir/EN/index.html" "$webadmin_install_dir/setup_domain.html" fi # Show the web admin index page (not the initial setup page) cp "$webadmin_install_dir/EN/index.html" "$webadmin_install_dir/index.html" rm "$webadmin_install_dir/index.prev" fi # Remove the initial setup page if [ -f "$webadmin_install_dir/setup.prev" ]; then rm "$webadmin_install_dir/setup.prev" fi } function remove_temporary_setup_files { # remove the file which indicates that the setup screen is active if [ -f "$webadmin_install_dir/.setupscreenactive" ]; then rm "$webadmin_install_dir/.setupscreenactive" fi # remove the setup file created by setup.php if [ -f "$setup_file" ]; then rm "$setup_file" fi # remove the file containing the domain name if [ -f "$domain_file" ]; then rm "$domain_file" fi } function restore_webadmin_files { # restore files which were removed for the initial setup if [ -d "$INSTALL_DIR/tempwebadmin" ]; then mv "$INSTALL_DIR/tempwebadmin"/* "$webadmin_install_dir" rm -rf "$INSTALL_DIR/tempwebadmin" fi } function set_webadmin_permissions { # set permissions for web admin site at freedombone.local chown www-data:www-data "$webadmin_install_dir/*.html" } function check_for_existing_processes { script_name="$1" { echo '#!/bin/bash'; echo ''; echo 'function exit_if_process_is_running {'; echo " process_name=\"\$1\""; echo " process_exists=\$(ps a | grep \"\$process_name\" | grep -v 'grep')"; echo " if [ \"\$process_exists\" ]; then"; echo " if [[ \"\$process_exists\" != *'grep'* ]]; then"; echo " process_id=\$(echo \"\$process_exists\" | awk -F ' ' '{print \$1}')"; echo " if [ \"\$process_id\" ]; then"; echo " if [[ \"$script_name\" != *\"\$process_name\" ]]; then"; echo " echo \"\$process_name is running\""; echo " exit 0"; echo ' fi'; echo ' fi'; echo ' fi'; echo ' fi'; echo '}'; echo ''; echo 'exit_if_process_is_running fbone_installer.sh'; echo 'exit_if_process_is_running webadmin_factory_reset.sh'; echo 'exit_if_process_is_running webadmin_appsettings.sh'; echo 'exit_if_process_is_running webadmin_upgrade.sh'; echo 'exit_if_process_is_running webadmin_format.sh'; echo 'exit_if_process_is_running backup-local'; echo 'exit_if_process_is_running addremove'; echo 'exit_if_process_is_running webadmin_backup.sh'; echo 'exit_if_process_is_running webadmin_backup_keys.sh'; echo 'exit_if_process_is_running restore-local'; echo 'exit_if_process_is_running webadmin_restore.sh'; echo 'exit_if_process_is_running webadmin_restore_keys.sh'; echo 'exit_if_process_is_running webadmin_new_user.sh'; echo 'exit_if_process_is_running webadmin_remove_user.sh'; echo ''; } > "$script_name" } function run_setup_command { if [ $install_state -ne $INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED ]; then return fi check_for_existing_processes $installer_script { echo "echo \"Beginning install \$(date)\" > $webadmin_install_dir/log.txt"; echo "chown www-data:www-data $webadmin_install_dir/log.txt"; echo ''; echo "/usr/local/bin/freedombone -c \"$CONFIGURATION_FILE\" >> $webadmin_install_dir/log.txt;"; echo "if ! grep -q 'install_final' \"$COMPLETION_FILE\"; then"; echo " chown www-data:www-data $webadmin_install_dir/log.txt"; echo " echo '$INSTALL_STATE_COMMAND_FAIL' > $install_state_file"; echo ' exit 36'; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/log.txt"; echo ''; echo "exit 0"; } >> $installer_script chmod +x $installer_script echo -n "$INSTALL_STATE_RUNNING_COMMAND" > "$install_state_file" install_state=$INSTALL_STATE_RUNNING_COMMAND # run in a separate process ./$installer_script & } function check_install_command_state { if [ $install_state -ne $INSTALL_STATE_RUNNING_COMMAND ]; then return fi reset_install_state= if [ ! -f "$install_state_file" ]; then reset_install_state=1 else curr_state=$(cat "$install_state_file") # shellcheck disable=SC2086 if [ $curr_state -eq $INSTALL_STATE_COMMAND_FAIL ]; then reset_install_state=1 fi install_has_finished= # shellcheck disable=SC2086 if [ $curr_state -eq $INSTALL_STATE_COMMAND_SUCCESS ]; then install_has_finished=1 else # Also check the install log for a message # indicating completion has happened if [ -f "$webadmin_install_dir/log.txt" ]; then end_of_log=$(tail -n 10 "$webadmin_install_dir/log.txt" | grep ${PROJECT_NAME}) end_of_log_message=$'installation is complete' if [[ "$end_of_log" == *"$end_of_log_message"* ]]; then install_has_finished=1 fi fi fi if [ $install_has_finished ]; then echo -n "$INSTALL_STATE_COMMAND_SUCCESS" > "$install_state_file" install_state=$INSTALL_STATE_COMMAND_SUCCESS restore_webadmin_files fi fi if [ $reset_install_state ]; then chown www-data:www-data "$webadmin_install_dir/log.txt" # remove the setup file containing login details if [ -f "$setup_file" ]; then rm "$setup_file" fi # remove the webadmin password file if [ -f /etc/nginx/.webadminpasswd ]; then rm /etc/nginx/.webadminpasswd fi echo -n "$INSTALL_STATE_FIRST_BOOT" > "$install_state_file" install_state=$INSTALL_STATE_FIRST_BOOT fi } function before_setup_runs { if [ $install_state -ne $INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED ]; then return fi if [ ! -f /etc/nginx/.webadminpasswd ]; then return fi if grep -q 'install_final' "$COMPLETION_FILE"; then return fi if [ ! -f "/usr/share/${PROJECT_NAME}/webadmin/EN/setup_installing.html" ]; then return fi cp "/usr/share/${PROJECT_NAME}/webadmin/EN/setup_installing.html" "$webadmin_install_dir/index.html" # get the username and domain from the .temp_setup.txt file # created by setup.php MY_USERNAME=$(cat "$setup_file") if [ ! "$MY_USERNAME" ]; then MY_USERNAME="$webadmin_user" else if [[ "$MY_USERNAME" != "$webadmin_user" ]]; then temp_webadmin_password=$(cat $webadmin_temp_password_file) web_admin_create_user "$webadmin_user" "$temp_webadmin_password" webadmin_user="$MY_USERNAME" fi fi DEFAULT_DOMAIN_NAME=${local_hostname} if [ -f "$domain_file" ]; then DEFAULT_DOMAIN_NAME=$(cat "$domain_file") fi # change the username in the config file if grep -q 'MY_USERNAME=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "MY_USERNAME=$MY_USERNAME" "$CONFIGURATION_FILE"; then sed -i "s|MY_USERNAME=.*|MY_USERNAME=$MY_USERNAME|g" "$CONFIGURATION_FILE" fi else echo "MY_USERNAME=$MY_USERNAME" >> "$CONFIGURATION_FILE" fi # change the full name in the config file if grep -q 'MY_NAME=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "MY_NAME=$MY_USERNAME" "$CONFIGURATION_FILE"; then sed -i "s|MY_NAME=.*|MY_USERNAME=$MY_USERNAME|g" "$CONFIGURATION_FILE" fi else echo "MY_NAME=$MY_USERNAME" >> "$CONFIGURATION_FILE" fi # change the default domain in the config file if grep -q 'DEFAULT_DOMAIN_NAME=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME" "$CONFIGURATION_FILE"; then sed -i "s|DEFAULT_DOMAIN_NAME=.*|DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME|g" "$CONFIGURATION_FILE" fi else echo "DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME" >> "$CONFIGURATION_FILE" fi # ensure that minimal install is set if grep -q 'MINIMAL_INSTALL=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "MINIMAL_INSTALL=yes" "$CONFIGURATION_FILE"; then sed -i 's|MINIMAL_INSTALL=.*|MINIMAL_INSTALL=yes|g' "$CONFIGURATION_FILE" fi else echo 'MINIMAL_INSTALL=yes' >> "$CONFIGURATION_FILE" fi # ensure that no DDNS provider is specified if grep -q 'DDNS_PROVIDER=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "DDNS_PROVIDER=none" "$CONFIGURATION_FILE"; then sed -i 's|DDNS_PROVIDER=.*|DDNS_PROVIDER=none|g' "$CONFIGURATION_FILE" fi else echo 'DDNS_PROVIDER=none' >> "$CONFIGURATION_FILE" fi run_setup_command } function after_setup_has_finished { if [ $install_state -ne $INSTALL_STATE_COMMAND_SUCCESS ]; then return fi if [ -f /root/.initial_setup ]; then rm /root/.initial_setup fi if [ -f $webadmin_temp_password_file ]; then rm $webadmin_temp_password_file fi increment_install_progress web_admin_onion_only increment_install_progress web_admin_create_users increment_install_progress web_admin_create_installed_apps increment_install_progress web_admin_create_add_apps increment_install_progress webadmin_update_version increment_install_progress if [ -d /etc/searx ]; then # new searx secret if [ -f "/etc/searx/searx/settings.yml" ]; then sed -i "s|secret_key :.*|secret_key : \"$(create_random_string 30)\"|g" "/etc/searx/searx/settings.yml" fi # update searx #cd /etc/searx || return #./manage.sh update_packages chown -R searx:searx /etc/searx systemctl restart searx fi increment_install_progress # remove default user if [ -d /home/fbone ]; then userdel -r fbone if [ -d /home/fbone ]; then rm -rf /home/fbone fi fi increment_install_progress systemctl restart nginx if [ -f $installer_script ]; then rm $installer_script fi increment_install_progress regenerate_blocklist regenerate_blocklist_muted_words increment_install_progress web_create_homepage increment_install_progress chown -R www-data:www-data "$webadmin_install_dir" enable_webadmin_login remove_initial_setup_page set_webadmin_permissions remove_temporary_setup_files systemctl reboot -i } function install_apps_from_webadmin { if [ -f "$pending_installs" ]; then linestr=$(head -n 1 "$pending_installs") if [[ "$linestr" == "install_"* && "$linestr" != *'_running'* ]]; then app_name=$(echo "$linestr" | awk -F '_' '{print $2}' | awk -F ',' '{print $1}') if [ -f "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" ]; then app_domain=$(echo "$linestr" | awk -F ',' '{print $2}') if [ ! "$app_domain" ]; then app_domain=${app_name}.local fi app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}') # indicate that we are installing sed -i "s|${app_name}|${app_name}_running|g" "$pending_installs" # Add domain name to the config if ! grep -q "${app_name_upper}_DOMAIN_NAME=" "$CONFIGURATION_FILE"; then echo "${app_name_upper}_DOMAIN_NAME=${app_domain}" >> "$CONFIGURATION_FILE" else sed -i "s|${app_name_upper}_DOMAIN_NAME=.*|${app_name_upper}_DOMAIN_NAME=${app_domain}|g" "$CONFIGURATION_FILE" fi # remove app from the removed file if grep -Fxq "_${app_name}_" "$REMOVED_APPS_FILE"; then sed -i "/_${app_name}_/d" "$REMOVED_APPS_FILE" fi # remove the qrcode for the app if it exists if [ -f "$webadmin_install_dir/app_qrcode_${app_name}.png" ]; then rm "$webadmin_install_dir/app_qrcode_${app_name}.png" fi # remove from pending list so that if the install gets stuck # it won't repeatedly try to install a bad app sed -i "/$linestr/d" "$pending_installs" if ! /usr/bin/timeout $APP_INSTALL_TIMEOUT_SEC /usr/local/bin/${PROJECT_NAME}-addremove add "${app_name}" > "$webadmin_install_dir/applog.txt"; then sed -i "/$linestr/d" "$pending_installs" notification_str="Failed to install. For details see admin/applog.txt" else notification_str="Installed successfully" fi translated_notification_str=$(web_admin_translate_text "$notification_str") /usr/local/bin/${PROJECT_NAME}-notification -s "[${PROJECT_NAME}] ${app_name} ${translated_notification_str}" -m "${app_name} ${translated_notification_str}" & chown www-data:www-data "$webadmin_install_dir/applog.txt" else # remove from pending list sed -i "/$linestr/d" "$pending_installs" fi else # if any unusual line is found then remove the file rm "$pending_installs" fi fi } function remove_apps_from_webadmin { if [ -f "$pending_removes" ]; then linestr=$(head -n 1 "$pending_removes") if [[ "$linestr" == "remove_"* ]]; then app_name=$(echo "$linestr" | awk -F '_' '{print $2}') if [ -f "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" ]; then # indicate that we are removing if [[ "$linestr" != *'_running'* ]]; then sed -i "s|${app_name}|${app_name}_running|g" "$pending_removes" fi /usr/bin/timeout $APP_INSTALL_TIMEOUT_SEC /usr/local/bin/${PROJECT_NAME}-addremove remove "${app_name}" > "$webadmin_install_dir/applog.txt" chown www-data:www-data "$webadmin_install_dir/applog.txt" if [ -f "$webadmin_install_dir/app_qrcode_${app_name}.png" ]; then rm "$webadmin_install_dir/app_qrcode_${app_name}.png" fi notification_str="removed" translated_notification_str=$(web_admin_translate_text "$notification_str") /usr/local/bin/${PROJECT_NAME}-notification -s "[${PROJECT_NAME}] ${app_name}" -m "${app_name} ${translated_notification_str}" & # NOTE: we don't need to run web_admin_create_add_apps # because that happens anyway as part of addremove fi # remove the line sed -i "/$linestr/d" "$pending_removes" else # if any unusual line is found then remove the file rm "$pending_removes" fi fi } function update_progress_bar { if [ ! -f "$setup_file" ]; then return fi # shellcheck disable=SC2086 if [ $install_state -gt $INSTALL_STATE_RUNNING_COMMAND ]; then return fi if [ ! -f /root/.install_counter ]; then echo -n '1' > /root/.install_counter fi max_counter=286 installing_page="$webadmin_install_dir/setup_installing.html" progress_counter=$(cat /root/.install_counter) progress_percent=$((progress_counter * 100 / max_counter)) if [ $progress_percent -gt 100 ]; then progress_percent=100 fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$installing_page" if ! grep -q 'w3-container w3-blue' "$webadmin_install_dir/index.html"; then cp "$webadmin_install_dir/setup_installing.html" "$webadmin_install_dir/index.html" fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$webadmin_install_dir/index.html" } function increment_install_progress { install_comment=$"1" if [ -f /root/.install_counter ]; then install_counter=$(cat /root/.install_counter) else install_counter=0 fi if [ "$install_comment" ]; then echo "$install_comment" > /root/.install_comment fi install_counter=$((install_counter + 1)) echo -n "$install_counter" > /root/.install_counter update_progress_bar } function initiate_automatic_backup { backup_hour=3 if grep -q "BACKUP_HOUR=" "$CONFIGURATION_FILE"; then backup_hour=$(grep "BACKUP_HOUR=" "$CONFIGURATION_FILE" | awk -F '=' '{print $2}') else echo "BACKUP_HOUR=$backup_hour" >> "$CONFIGURATION_FILE" fi curr_hour=$(date +%H) if [ "$curr_hour" -eq "$backup_hour" ]; then if [ "$webadmin_prev_hour" -ne "$backup_hour" ]; then # check that backup drive is plugged in backup_device=$(detect_connected_drives) if [[ "$backup_device" == 'sd'* ]]; then touch "$backup_file" autobackup_log_file="$webadmin_install_dir/autobackup.txt" if [ -f "$autobackup_log_file" ]; then # keep the number of lines in the autobackup log small # we don't need to check things from ancient history backup_file_lines=$(wc -l < "$autobackup_log_file") # shellcheck disable=SC2086 if [ $backup_file_lines -gt 14 ]; then tail -n +2 "$autobackup_log_file" > /tmp/autobackup_file mv /tmp/autobackup_file "$autobackup_log_file" fi fi echo $"Backup initiated $(date)" >> "$autobackup_log_file" chown www-data:www-data "$autobackup_log_file" running_auto_backup=1 fi fi fi webadmin_prev_hour=$curr_hour } function update_backup_progress_bar { if [ ! -f "$backup_progress_file" ]; then return fi backup_process_exists= backup_process=$(pgrep 'webadmin_backup.sh' | grep -v 'grep') if [ "$backup_process" ]; then if [[ "$backup_process" != *'grep'* ]]; then backup_pid=$(echo "$backup_process" | awk -F ' ' '{print $1}') if [ "$backup_pid" ]; then backup_process_exists=1 fi fi fi if [ ! $backup_process_exists ]; then return fi max_counter=23 progress_page="$webadmin_install_dir/backup_progress.html" progress_counter=$(cat $backup_progress_file) progress_percent=$((progress_counter * 100 / max_counter)) if [ $progress_percent -gt 100 ]; then progress_percent=$((progress_percent - 100)) fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$progress_page" } function update_restore_progress_bar { if [ ! -f "$restore_progress_file" ]; then return fi restore_process_exists= restore_process=$(pgrep 'webadmin_restore.sh' | grep -v 'grep') if [ "$restore_process" ]; then if [[ "$restore_process" != *'grep'* ]]; then restore_pid=$(echo "$restore_process" | awk -F ' ' '{print $1}') if [ "$restore_pid" ]; then restore_process_exists=1 fi fi fi if [ ! $restore_process_exists ]; then return fi max_counter=23 progress_page="$webadmin_install_dir/restore_progress.html" progress_counter=$(cat $restore_progress_file) progress_percent=$((progress_counter * 100 / max_counter)) if [ $progress_percent -gt 100 ]; then progress_percent=$((progress_percent - 100)) fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$progress_page" } function update_format_progress_bar { if [ ! -f "$format_progress_file" ]; then return fi format_process_exists= format_process=$(pgrep 'webadmin_format.sh' | grep -v 'grep') if [ "$format_process" ]; then if [[ "$format_process" != *'grep'* ]]; then format_pid=$(echo "$format_process" | awk -F ' ' '{print $1}') if [ "$format_pid" ]; then format_process_exists=1 fi fi fi if [ ! $format_process_exists ]; then return fi max_counter=5 progress_page="$webadmin_install_dir/format_progress.html" progress_counter=$(cat $format_progress_file) progress_percent=$((progress_counter * 100 / max_counter)) if [ $progress_percent -gt 100 ]; then progress_percent=100 fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$progress_page" } function backup_and_restore { update_backup_progress_bar update_restore_progress_bar update_format_progress_bar initiate_automatic_backup if [ -f "$restore_file" ]; then rm "$restore_file" ADMIN_USERNAME=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | awk -F '=' '{print $2}') webadmin_onion_address=$(cat /var/lib/tor/hidden_service_webadmin/hostname) restore_title=$'Restore status' restore_failed_message=$"Restore failed. See http://${webadmin_onion_address}/admin/restore.txt for details" restore_success_message=$"Restore succeeded" check_for_existing_processes $restore_script { echo "echo \"Beginning webadmin restore \$(date)\" > $webadmin_install_dir/restore.txt"; echo "chown www-data:www-data $webadmin_install_dir/restore.txt"; echo ''; echo "cp $webadmin_install_dir/restore_progress_template.html $webadmin_install_dir/restore_progress.html"; echo "chown www-data:www-data $webadmin_install_dir/restore_progress.html"; echo ''; echo 'backup_password='; echo 'if [ -f /tmp/backup_password.txt ]; then'; echo " backup_password=\$(cat /tmp/backup_password.txt)"; echo " ${PROJECT_NAME}-pass -u \"$ADMIN_USERNAME\" -a simplebackup -p \"\$backup_password\""; echo ' rm /tmp/backup_password.txt'; echo 'else'; echo " backup_password=\$(${PROJECT_NAME}-pass -u \"$ADMIN_USERNAME\" -a simplebackup)"; echo 'fi'; echo ''; echo "if /usr/bin/timeout $BACKUP_TIMEOUT_SEC /usr/local/bin/${PROJECT_NAME}-restore-local simple \"\$backup_password\" >> $webadmin_install_dir/restore.txt; then"; echo " echo \"Completed \$(date)\" >> $webadmin_install_dir/restore.txt"; echo " cp $webadmin_install_dir/restore_complete.html $webadmin_install_dir/restore_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$restore_success_message\" -s \"[${PROJECT_NAME}] $restore_title\" &"; echo 'else'; echo " cp $webadmin_install_dir/restore_failed.html $webadmin_install_dir/restore_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$restore_failed_message\" -s \"[${PROJECT_NAME}] $restore_title\" &"; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/restore.txt"; echo "chown www-data:www-data $webadmin_install_dir/restore_progress.html"; echo ''; echo "rm $restore_progress_file"; echo ''; echo "exit 0"; } >> $restore_script chmod +x $restore_script # run in a separate process ./$restore_script & else if [ -f "$backup_file" ]; then rm "$backup_file" ADMIN_USERNAME=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | awk -F '=' '{print $2}') webadmin_onion_address=$(cat /var/lib/tor/hidden_service_webadmin/hostname) backup_title=$'Backup status' backup_failed_message=$"Backup failed. See http://${webadmin_onion_address}/admin/backup.txt for details" backup_success_message=$"Backup succeeded" backup_name='webadmin' if [ $running_auto_backup ]; then backup_name=$'scheduled' date >> "$webadmin_install_dir/autobackup.log" chown www-data:www-data "$webadmin_install_dir/autobackup.log" running_auto_backup= fi check_for_existing_processes $backup_script { echo "echo \"Beginning $backup_name backup \$(date)\" > $webadmin_install_dir/backup.txt"; echo "chown www-data:www-data $webadmin_install_dir/backup.txt"; echo ''; echo "cp $webadmin_install_dir/backup_progress_template.html $webadmin_install_dir/backup_progress.html"; echo "chown www-data:www-data $webadmin_install_dir/backup_progress.html"; echo ''; echo 'backup_password='; echo 'if [ -f /tmp/backup_password.txt ]; then'; echo " backup_password=\$(cat /tmp/backup_password.txt)"; echo " ${PROJECT_NAME}-pass -u \"$ADMIN_USERNAME\" -a simplebackup -p \"\$backup_password\""; echo ' rm /tmp/backup_password.txt'; echo " sed -i \"s|\\\"backup_password\\\".*|\\\"backup_password\\\" value=\\\"\$backup_password\\\"></p>|g\" $webadmin_install_dir/backup_password.html"; echo " sed -i \"s|\\\"backup_password_confirm\\\".*|\\\"backup_password_confirm\\\" value=\\\"\$backup_password\\\"></p>|g\" $webadmin_install_dir/backup_password.html"; echo " chown www-data:www-data $webadmin_install_dir/backup_password.html"; echo " sed -i \"s|\\\"backup_password\\\".*|\\\"backup_password\\\" value=\\\"\$backup_password\\\"></p>|g\" $webadmin_install_dir/restore_password.html"; echo " chown www-data:www-data $webadmin_install_dir/restore_password.html"; echo 'else'; echo " backup_password=\$(${PROJECT_NAME}-pass -u \"$ADMIN_USERNAME\" -a simplebackup)"; echo 'fi'; echo ''; echo "if /usr/bin/timeout $BACKUP_TIMEOUT_SEC /usr/local/bin/${PROJECT_NAME}-backup-local simple \"\$backup_password\" >> $webadmin_install_dir/backup.txt; then"; echo " echo \"Completed \$(date)\" >> $webadmin_install_dir/backup.txt"; echo " cp $webadmin_install_dir/backup_complete.html $webadmin_install_dir/backup_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$backup_success_message\" -s \"[${PROJECT_NAME}] $backup_title\" &"; echo 'else'; echo " cp $webadmin_install_dir/backup_failed.html $webadmin_install_dir/backup_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$backup_failed_message\" -s \"[${PROJECT_NAME}] $backup_title\" &"; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/backup.txt"; echo "chown www-data:www-data $webadmin_install_dir/backup_progress.html"; echo ''; echo "rm $backup_progress_file"; echo ''; echo "exit 0"; } >> $backup_script chmod +x $backup_script # run in a separate process ./$backup_script & else if [ -f "$format_file" ]; then rm "$format_file" webadmin_onion_address=$(cat /var/lib/tor/hidden_service_webadmin/hostname) format_title=$'USB format status' format_failed_message=$"USB format failed. See http://${webadmin_onion_address}/admin/format.txt for details" format_success_message=$"USB format succeeded" check_for_existing_processes $format_script { echo "if /usr/bin/timeout $FORMAT_TIMEOUT_SEC /usr/local/bin/${PROJECT_NAME}-format simple > $webadmin_install_dir/format.txt; then"; echo " cp $webadmin_install_dir/format_complete.html $webadmin_install_dir/format_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$format_success_message\" -s \"[${PROJECT_NAME}] $format_title\" &"; echo 'else'; echo " cp $webadmin_install_dir/format_failed.html $webadmin_install_dir/format_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$format_failed_message\" -s \"[${PROJECT_NAME}] $format_title\" &"; echo 'fi'; echo "chown www-data:www-data $webadmin_install_dir/format_progress.html"; echo ''; echo "rm $format_progress_file"; echo ''; echo "exit 0"; } >> $format_script chmod +x $format_script # run in a separate process ./$format_script & fi fi fi } function backup_and_restore_keys { if [ -f "$restore_keys_file" ]; then rm "$restore_keys_file" admin_username=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') # check_for_existing_processes $restore_keys_script { echo "echo \"Beginning webadmin restore keys \$(date)\" > $webadmin_install_dir/restore.txt"; echo "chown www-data:www-data $webadmin_install_dir/restore.txt"; echo ''; echo "cp $webadmin_install_dir/restore_keys_progress_template.html $webadmin_install_dir/restore_keys_progress.html"; echo "chown www-data:www-data $webadmin_install_dir/restore_keys_progress.html"; echo ''; echo "if /usr/local/bin/${PROJECT_NAME}-recoverkey -u \"$admin_username\" -d \"simple\" >> $webadmin_install_dir/restore.txt; then"; echo " echo \"Completed \$(date)\" >> $webadmin_install_dir/restore.txt"; echo " cp $webadmin_install_dir/restore_keys_complete.html $webadmin_install_dir/restore_keys_progress.html"; echo 'else'; echo " cp $webadmin_install_dir/restore_keys_failed.html $webadmin_install_dir/restore_keys_progress.html"; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/restore.txt"; echo "chown www-data:www-data $webadmin_install_dir/restore_keys_progress.html"; echo ''; echo "exit 0"; } >> $restore_keys_script chmod +x $restore_keys_script # run in a separate process ./$restore_keys_script & else if [ -f "$backup_keys_file" ]; then rm "$backup_keys_file" admin_username=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') check_for_existing_processes $backup_keys_script { echo "echo \"Beginning webadmin backup keys \$(date)\" > $webadmin_install_dir/backup.txt"; echo "chown www-data:www-data $webadmin_install_dir/backup.txt"; echo ''; echo "cp $webadmin_install_dir/backup_keys_progress_template.html $webadmin_install_dir/backup_keys_progress.html"; echo "chown www-data:www-data $webadmin_install_dir/backup_keys_progress.html"; echo ''; echo "if /usr/local/bin/${PROJECT_NAME}-keydrive -u \"$admin_username\" --master 'yes' -d \"simple\" >> $webadmin_install_dir/backup.txt; then"; echo " echo \"Completed \$(date)\" >> $webadmin_install_dir/backup.txt"; echo " cp $webadmin_install_dir/backup_keys_complete.html $webadmin_install_dir/backup_keys_progress.html"; echo 'else'; echo " cp $webadmin_install_dir/backup_keys_failed.html $webadmin_install_dir/backup_keys_progress.html"; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/backup.txt"; echo "chown www-data:www-data $webadmin_install_dir/backup_keys_progress.html"; echo ''; echo "exit 0"; } >> $backup_keys_script chmod +x $backup_keys_script # run in a separate process ./$backup_keys_script & fi fi } function is_valid_user { USRNAME="$1" if [[ "$USRNAME" != "turtl" && "$USRNAME" != "znc" && "$USRNAME" != "pihole" && "$USRNAME" != "fbone" && "$USRNAME" != "go" && "$USRNAME" != "gogs" && "$USRNAME" != "git" && "$USRNAME" != "sync" && "$USRNAME" != "tahoelafs" ]]; then echo "1" else echo "0" fi } function valid_username_characters { local re='^[[:lower:]_][[:lower:][:digit:]_-]{2,15}$' (( ${#1} > 16 )) && return 1 [[ $1 =~ $re ]] # return value of this comparison is used for the function } function add_remove_users { if [ -f "$new_user_file" ]; then new_username=$(awk -F ',' '{print $1}' < "$new_user_file") if [ ${#new_username} -ge 3 ]; then if [ ${#new_username} -le 32 ]; then if valid_username_characters "$new_username"; then if [ ! -d "/home/$new_username" ]; then if [[ $(is_valid_user "$new_username") == "1" ]]; then new_password=$(awk -F ',' '{print $2}' < "$new_user_file") check_for_existing_processes $new_user_script { echo "/usr/local/bin/${PROJECT_NAME}-adduser $new_username password=$new_password > $webadmin_install_dir/log.txt"; echo "exit 0"; } >> $new_user_script chmod +x $new_user_script # run in a separate process ./$new_user_script & new_password= fi fi fi fi fi rm "$new_user_file" fi if [ -f "$remove_user_file" ]; then remove_username=$(cat "$remove_user_file") if [ ${#remove_username} -ge 3 ]; then if [ ${#remove_username} -le 32 ]; then if valid_username_characters "$remove_username"; then if [ -d "/home/$remove_username" ]; then if [[ $(is_valid_user "$remove_username") == "1" ]]; then admin_username=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [[ "$remove_username" != "$admin_username" ]]; then check_for_existing_processes $remove_user_script { echo "/usr/local/bin/${PROJECT_NAME}-rmuser $remove_username -f > $webadmin_install_dir/log.txt"; echo "exit 0"; } >> $remove_user_script chmod +x $remove_user_script # run in a separate process ./$remove_user_script & fi fi fi fi fi fi rm "$remove_user_file" fi } function webadmin_change_password { if [ ! -f "$change_password_file" ]; then return fi temp_password_file=$(cat "$change_password_file") if [ -f "$temp_password_file" ]; then curr_username=$(awk -F ',' '{print $1}' < "$temp_password_file") if [ ${#curr_username} -ge 3 ]; then if [[ $(is_valid_user "$curr_username") == "1" ]]; then if [ -d "/home/$curr_username" ]; then new_password=$(awk -F ',' '{print $2}' < "$temp_password_file") admin_username=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') # change the webadmin login if [[ "$curr_username" == "$admin_username" ]]; then if [ -f /etc/nginx/.webadminpasswd ]; then sed -i "/${curr_username}:/d" /etc/nginx/.webadminpasswd fi echo -n "$new_password" | htpasswd -i -s -c /etc/nginx/.webadminpasswd "$curr_username" echo -n "$new_password" > ${IMAGE_PASSWORD_FILE} fi # change the login for the user echo -n "${curr_username}:${new_password}" | /usr/sbin/chpasswd # change passwords for each installed app /usr/local/bin/${PROJECT_NAME}-chpasswd "$curr_username" "$new_password" # change the backup password ${PROJECT_NAME}-pass -u admin -a simplebackup -p "$new_password" new_password= fi fi fi rm "$temp_password_file" fi rm "$change_password_file" } function webadmin_upgrade { if [ -f "$upgrade_file" ]; then rm "$upgrade_file" check_for_existing_processes $upgrade_script { echo "echo \"Beginning webadmin upgrade \$(date)\" > $webadmin_install_dir/upgrade.txt"; echo "chown www-data:www-data $webadmin_install_dir/upgrade.txt"; echo ''; echo "/usr/local/bin/${PROJECT_NAME}-upgrade >> $webadmin_install_dir/upgrade.txt"; echo ''; echo "chown www-data:www-data $webadmin_install_dir/upgrade.txt"; echo ''; echo "exit 0"; } >> $upgrade_script chmod +x $upgrade_script # run in a separate process ./$upgrade_script & fi } function webadmin_factory_reset { if [ -f "$factoryreset_file" ]; then rm "$factoryreset_file" check_for_existing_processes $factoryreset_script { echo "echo \"Beginning webadmin factory reset \$(date)\" > $webadmin_install_dir/factoryreset.txt"; echo "chown www-data:www-data $webadmin_install_dir/factoryreset.txt"; echo ''; echo "/usr/local/bin/${PROJECT_NAME}-factory-reset -f >> $webadmin_install_dir/factoryreset.txt"; echo ''; echo "chown www-data:www-data $webadmin_install_dir/factoryreset.txt"; echo ''; echo "exit 0"; } >> $factoryreset_script chmod +x $factoryreset_script # run in a separate process ./$factoryreset_script & fi } function reset_shutdown { if [ -f "$shutdown_file" ]; then rm "$shutdown_file" if [ -f "$reset_file" ]; then rm "$reset_file" fi sleep 2 systemctl poweroff fi if [ -f "$reset_file" ]; then rm "$reset_file" if [ -f "$shutdown_file" ]; then rm "$shutdown_file" fi sleep 2 systemctl reboot -i fi } function regenerate_blocklist { if [ ! -f "$FIREWALL_DOMAINS" ]; then touch "$FIREWALL_DOMAINS" fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/blocking_template.html" ]; then cp "$webadmin_install_dir/blocking_template.html" "$webadmin_install_dir/blocking.html" blockedlist=$(sed 's@[/\&]@\\&@g;s/$/\\/' "$FIREWALL_DOMAINS"; echo .) blockedlist=${blockedlist%.} sed -i "s|BLOCKEDLIST|$blockedlist|g" "$webadmin_install_dir/blocking.html" chown www-data:www-data "$webadmin_install_dir/blocking.html" fi } function regenerate_blocklist_muted_words { if [ ! -f "$MUTED_WORDS" ]; then touch "$MUTED_WORDS" fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/blocking_words_template.html" ]; then cp "$webadmin_install_dir/blocking_words_template.html" "$webadmin_install_dir/blocking_words.html" blockedlistwords=$(sed 's@[/\&]@\\&@g;s/$/\\/' "$MUTED_WORDS"; echo .) blockedlistwords=${blockedlistwords%.} sed -i "s|BLOCKEDWORDSLIST|$blockedlistwords|g" "$webadmin_install_dir/blocking_words.html" chown www-data:www-data "$webadmin_install_dir/blocking_words.html" fi } function regenerate_bridges { if [ ! -f "/root/.webadmin_torbridges" ]; then touch "/root/.webadmin_torbridges" fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/bridges_template.html" ]; then cp "$webadmin_install_dir/bridges_template.html" "$webadmin_install_dir/bridges.html" bridgeslist=$(sed 's@[/\&]@\\&@g;s/$/\\/' /root/.webadmin_torbridges; echo .) bridgeslist=${bridgeslist%.} sed -i "s|TORBRIDGES|$bridgeslist|g" "$webadmin_install_dir/bridges.html" chown www-data:www-data "$webadmin_install_dir/bridges.html" fi } function regenerate_dynamic_dns { ddns="$1" ddns_username="$2" ddns_password="$3" ddns_code="$4" local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/dynamicdns_template.html" ]; then cp "$webadmin_install_dir/dynamicdns_template.html" "$webadmin_install_dir/dynamicdns.html" if [[ "$ddns" == 'default@freedns.afraid.org' ]]; then ddns='freedns' fi if [[ "$ddns" == 'dyn.com' ]]; then ddns='dyn' fi sed -i "s|\"$ddns\"|\"$ddns\" selected|g" "$webadmin_install_dir/dynamicdns.html" sed -i "s|DDNS_USERNAME|$ddns_username|g" "$webadmin_install_dir/dynamicdns.html" sed -i "s|DDNS_CODE|$ddns_code|g" "$webadmin_install_dir/dynamicdns.html" sed -i "s|CURRENT_IP_ADDRESS|$(get_external_ipv4_address)|g" "$webadmin_install_dir/dynamicdns.html" chown www-data:www-data "$webadmin_install_dir/dynamicdns.html" fi } function syncthing_update_settings_template { # Creates the syncthing settings screen within webadmin # shellcheck disable=SC2154 app_settings_screen_template="$webadmin_install_dir/settings_syncthing_template.html" app_settings_screen="$webadmin_install_dir/settings_syncthing.html" cp "$app_settings_screen_template" "$app_settings_screen" syncthinglist=$(sed 's@[/\&]@\\&@g;s/$/\\/' "/home/$MY_USERNAME/.syncthingids"; echo .) syncthinglist=${syncthinglist%.} sed -i "s|SYNCTHINGIDS|$syncthinglist|g" "$app_settings_screen" chown www-data:www-data "$app_settings_screen" } function smolrss_update_settings_template { # Creates rss feeds list within the web UI # shellcheck disable=SC2154 app_settings_screen_template="$webadmin_install_dir/settings_smolrss_template.html" app_settings_screen="$webadmin_install_dir/settings_smolrss.html" cp "$app_settings_screen_template" "$app_settings_screen" feedslist=$(sed 's@[/\&]@\\&@g;s/$/\\/' "/var/www/$SMOLRSS_DOMAIN_NAME/htdocs/feeds.txt"; echo .) feedslist=${feedslist%.} sed -i "s|RSSFEEDS|$feedslist|g" "$app_settings_screen" chown www-data:www-data "$app_settings_screen" } function datserver_update_settings_template { # Creates dat links list within the web UI # shellcheck disable=SC2154 app_settings_screen_template="$webadmin_install_dir/settings_datserver_template.html" app_settings_screen="$webadmin_install_dir/settings_datserver.html" cp "$app_settings_screen_template" "$app_settings_screen" datlinks=$(sed 's@[/\&]@\\&@g;s/$/\\/' "/etc/datserver/feeds"; echo .) datlinks=${datlinks%.} sed -i "s|DATLINKS|$datlinks|g" "$app_settings_screen" chown www-data:www-data "$app_settings_screen" } function update_syncthing { if [ -f "$syncthing_file" ]; then MY_USERNAME=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | awk -F '=' '{print $2}') syncthingids_new="/home/$MY_USERNAME/.syncthingids.webadmin" if [ -f "$syncthingids_new" ]; then rm "$syncthingids_new" fi touch "$syncthingids_new" # add an extra line, otherwise the last line may not parse echo "" >> "$syncthing_file" syncthing_lines_ctr=0 while read -r line; do if [ $syncthing_lines_ctr -gt 1024 ]; then # This prevents someone copy-pasting a giant amount of text # into the syncthing ids. break fi syncthing_lines_ctr=$((syncthing_lines_ctr + 1)) if [ "$line" ]; then # remove leading and trailing spaces newline="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" echo "$newline" >> "$syncthingids_new" fi done < "$syncthing_file" mv "/home/$MY_USERNAME/.syncthingids" "/home/$MY_USERNAME/.syncthingids.backup" mv "$syncthingids_new" "/home/$MY_USERNAME/.syncthingids" chown "$MY_USERNAME":"$MY_USERNAME" "/home/$MY_USERNAME/.syncthingids" rm "$syncthing_file" syncthing_update_settings_template touch "/home/$MY_USERNAME/.syncthing-update" chown "$MY_USERNAME":"$MY_USERNAME" "/home/$MY_USERNAME/.syncthing-update" fi } function update_icecast { if [ -f "$icecast_file" ]; then if [ -d /etc/icecast2 ]; then ICECAST_TITLE=$(awk -F ',' '{print $1}' < "$icecast_file") ICECAST_DESCRIPTION=$(awk -F ',' '{print $2}' < "$icecast_file") icecast_genre=$(awk -F ',' '{print $3}' < "$icecast_file") if [[ "$ICECAST_TITLE" != '' && "$ICECAST_DESCRIPTION" != '' && "$icecast_genre" != '' ]]; then ADMIN_USERNAME=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | awk -F '=' '{print $2}') ICECAST_SOURCE_PASSWORD=$("${PROJECT_NAME}-pass" -u "$ADMIN_USERNAME" -a icecastsource) ICECAST_USER_PASSWORD=$("${PROJECT_NAME}-pass" -u "$ADMIN_USERNAME" -a icecastuser) ICECAST_TITLE_MAIN="$ICECAST_DESCRIPTION" { echo '#Settings'; echo ''; echo 'set("log.file.path", "/dev/null")'; echo 'set("server.telnet", false)'; echo 'set("harbor.bind_addr","0.0.0.0")'; echo ''; echo '# Music playlists'; echo "music1 = nrj(playlist.safe(\"$ICECAST_DIR\"))"; echo ''; echo '# Some jingles'; echo "jingles = nrj(playlist.safe(\"$ICECAST_JINGLES\"))"; echo ''; echo '# If something goes wrong, well play this'; echo 'security = single("/etc/icecast2/default.ogg")'; echo ''; echo '# Start building the feed with music'; echo 'radio = random([music1])'; echo ''; echo '# Add the security, requests and smart crossfade'; echo 'radio = fallback(track_sensitive = false,[smart_crossfade(fallback([request.queue(id="request"),radio])), security])'; echo ''; echo '# Now add some jingles'; echo 'radio = random(weights=[1,2],[jingles,radio])'; echo ''; echo '# Add a skip command for the music stream'; echo '#server.register('; echo '#usage="skip",'; echo '#description="Skip the current song.",'; echo '#"skip",'; echo '#fun(_) -> begin source.skip(radio) "Done!" end'; echo ''; echo '# Talk over stream using microphone mount.'; echo "#mic = input.harbor(\"mic\",port=8080,password=\"$ICECAST_USER_PASSWORD\",buffer=15.0,max=30.0)"; echo '#radio = smooth_add(delay=0.8, p=0.15, normal=radio, special=mic)'; echo ''; echo '#Add support for live streams.'; echo "#live = audio_to_stereo(input.harbor(\"live\", port=8080, password=\"$ICECAST_USER_PASSWORD\", buffer=15.0, max=30.0))"; echo '#full = fallback(track_sensitive=false, [live,radio])'; echo ''; echo '# Stream it out'; echo '#output.icecast(%mp3.vbr,'; echo "#host = \"localhost\", port = $ICECAST_PORT, password = \"$ICECAST_SOURCE_PASSWORD\", mount = \"music.mp3\", name=\"$ICECAST_TITLE\", description=\"$ICECAST_DESCRIPTION\",radio)"; echo ''; echo '#output.icecast(%vorbis,'; echo "#host = \"localhost\", port = $ICECAST_PORT,"; echo "#password = \"$ICECAST_SOURCE_PASSWORD\", mount = \"music.ogg\","; echo "#name=\"$ICECAST_TITLE\", description=\"$ICECAST_DESCRIPTION\",radio)"; echo ''; echo '#output.icecast(%opus(vbr="unconstrained",bitrate=5),'; echo "#host = \"localhost\", port = $ICECAST_PORT,"; echo "#password = \"$ICECAST_SOURCE_PASSWORD\", mount = \"music.opus\","; echo "#name=\"$ICECAST_TITLE\", description=\"$ICECAST_DESCRIPTION\",radio)"; echo ''; echo "#output.icecast(%mp3.vbr, host = \"localhost\", port = $ICECAST_PORT, password = \"$ICECAST_SOURCE_PASSWORD\", mount = \"stream.mp3\", name=\"$ICECAST_TITLE_MAIN\", description=\"$ICECAST_TITLE_MAIN\", full)"; echo ''; echo "#output.icecast(%vorbis(samplerate=8000, channels=2, quality=0.1), host=\"localhost\", port=$ICECAST_PORT, password=\"$ICECAST_SOURCE_PASSWORD\", mount=\"stream.ogg\", name=\"$ICECAST_TITLE_MAIN\", description=\"$ICECAST_TITLE_MAIN\",full)"; echo ''; echo "output.icecast(%opus(vbr=\"unconstrained\",bitrate=20), description=\"$ICECAST_TITLE_MAIN\", host=\"localhost\", port=$ICECAST_PORT, password=\"$ICECAST_SOURCE_PASSWORD\", mount=\"stream.opus\", radio)"; } > "$liquidsoap_script" chown liquidsoapuser:icecast "$liquidsoap_script" sed -i "s|\"icecast_name\".*|\"icecast_name\" value=\"$ICECAST_TITLE\">|g" "$webadmin_install_dir/settings_icecast.html" sed -i "s|\"icecast_description\".*|\"icecast_description\" value=\"$ICECAST_DESCRIPTION\">|g" "$webadmin_install_dir/settings_icecast.html" sed -i "s|\"icecast_genre\".*|\"icecast_genre\" value=\"$icecast_genre\">|g" "$webadmin_install_dir/settings_icecast.html" icecast_usb_drive=$(detect_connected_drives) if [ "$icecast_usb_drive" ]; then icecast_playlist_updated= backup_mount_drive "$icecast_usb_drive" if [ $backup_drive_mounted ]; then icecast_import_dir="$USB_MOUNT/playlist" # search some common directory names if [ ! -d "$icecast_import_dir" ]; then icecast_import_dir="$USB_MOUNT/icecast" fi if [ ! -d "$icecast_import_dir" ]; then icecast_import_dir="$USB_MOUNT/radio" fi if [ ! -d "$icecast_import_dir" ]; then icecast_import_dir="$USB_MOUNT/stream" fi if [ ! -d "$icecast_import_dir" ]; then icecast_import_dir="$USB_MOUNT/music" fi if [ -d "$icecast_import_dir" ]; then if [ -d "$ICECAST_DIR" ]; then stop_icecast # remove any existing playlist # shellcheck disable=SC2115 rm -rf $ICECAST_DIR/* # shellcheck disable=SC2115 rm -rf $ICECAST_JINGLES/* # copy the new files cp -ru "$icecast_import_dir/"* "$ICECAST_DIR" cd "$ICECAST_DIR" || return for name in *; do mv "$name" "${name// /_}"; done icecast_playlist_updated=1 fi fi fi backup_unmount_drive if [ $icecast_playlist_updated ]; then # move default file if [ -f $ICECAST_DIR/default.ogg ]; then mv $ICECAST_DIR/default.ogg /etc/icecast2/default.ogg chown icecast2:icecast /etc/icecast2/default.ogg fi # move jingles mv $ICECAST_DIR/jingle* $ICECAST_JINGLES mv $ICECAST_DIR/Jingle* $ICECAST_JINGLES chown -R liquidsoapuser:icecast $ICECAST_DIR chown -R liquidsoapuser:icecast $ICECAST_JINGLES icecast_import_subject=$'[Freedombone] Playlist imported' icecast_import_msg=$'Playlist was imported from USB drive' start_icecast icecast_notification_file=/root/.icecast_import_msg.sh { echo '#!/bin/bash'; echo "/usr/local/bin/${PROJECT_NAME}-notification -s '$icecast_import_subject' -m '$icecast_import_msg'"; } > "$icecast_notification_file" chmod +x "$icecast_notification_file" ./$icecast_notification_file & rm "$icecast_file" return fi fi stop_icecast start_icecast fi fi rm "$icecast_file" fi } function update_koel { if [ -f "$koel_file" ]; then if [ -d /music ]; then koel_usb_drive=$(detect_connected_drives) if [ "$koel_usb_drive" ]; then backup_mount_drive "$koel_usb_drive" if [ $backup_drive_mounted ]; then koel_import_dir="$USB_MOUNT/Music" # search some common directory names if [ ! -d "$koel_import_dir" ]; then koel_import_dir="$USB_MOUNT/music" fi if [ -d "$koel_import_dir" ]; then # copy the new files cp -ru "$koel_import_dir/"* /music fi backup_unmount_drive fi fi fi rm "$koel_file" fi } function update_dlna { if [ -f "$dlna_file" ]; then if [ ! -f /etc/minidlna.conf ]; then dlna_usb_drive=$(detect_connected_drives) if [ "$dlna_usb_drive" ]; then backup_mount_drive "$dlna_usb_drive" if [ $backup_drive_mounted ]; then # music dlna_import_dir="$USB_MOUNT/Music" if [ ! -d "$dlna_import_dir" ]; then dlna_import_dir="$USB_MOUNT/music" fi if [ -d "$dlna_import_dir" ]; then cp -ru "$dlna_import_dir/"* /music chown -R minidlna:minidlna /music fi # pictures dlna_import_dir="$USB_MOUNT/Pictures" if [ ! -d "$dlna_import_dir" ]; then dlna_import_dir="$USB_MOUNT/pictures" fi if [ ! -d "$dlna_import_dir" ]; then dlna_import_dir="$USB_MOUNT/Photos" fi if [ ! -d "$dlna_import_dir" ]; then dlna_import_dir="$USB_MOUNT/photos" fi if [ ! -d "$dlna_import_dir" ]; then dlna_import_dir="$USB_MOUNT/DCIM" fi if [ -d "$dlna_import_dir" ]; then cp -ru "$dlna_import_dir/"* /pictures chown -R minidlna:minidlna /pictures fi # videos dlna_import_dir="$USB_MOUNT/Videos" if [ ! -d "$dlna_import_dir" ]; then dlna_import_dir="$USB_MOUNT/videos" fi if [ -d "$dlna_import_dir" ]; then cp -ru "$dlna_import_dir/"* /videos chown -R minidlna:minidlna /videos fi backup_unmount_drive systemctl restart minidlna minidlnad -R fi fi fi rm "$dlna_file" fi } function update_smolrss { if [ -f "$smolrss_file" ]; then SMOLRSS_DOMAIN_NAME=$(grep 'SMOLRSS_DOMAIN_NAME=' "$CONFIGURATION_FILE" | awk -F '=' '{print $2}') cd "/var/www/$SMOLRSS_DOMAIN_NAME/htdocs" || return if [ -f "feeds.new" ]; then rm "feeds.new" fi touch "feeds.new" # add an extra line, otherwise the last line may not parse echo "" >> "$smolrss_file" feeds_lines_ctr=0 while read -r line; do if [ $feeds_lines_ctr -gt 1024 ]; then # This prevents someone copy-pasting a giant amount of text # into the rss feeds break fi feeds_lines_ctr=$((feeds_lines_ctr + 1)) if [ "$line" ]; then # remove leading and trailing spaces newline="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" echo "$newline" >> "feeds.new" fi done < "$smolrss_file" mv "feeds.new" feeds.txt ./create_feeds feeds.txt > feeds.xml chown www-data:www-data feeds.txt rm "$smolrss_file" smolrss_update_settings_template fi } function update_dat_links { if [ -f "$datlinks_file" ]; then cd "/etc/datserver" || return if [ -f "feeds.new" ]; then rm "feeds.new" fi touch "feeds.new" # add an extra line, otherwise the last line may not parse echo "" >> "$datlinks_file" datlinks_lines_ctr=0 while read -r line; do if [ $datlinks_lines_ctr -gt 1024 ]; then # This prevents someone copy-pasting a giant amount of text # into the dat links break fi datlinks_lines_ctr=$((datlinks_lines_ctr + 1)) if [ "$line" ]; then # remove leading and trailing spaces newline="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" if [[ "$newline" == 'dat://'* ]]; then echo "$newline" >> "feeds.new" fi fi done < "$datlinks_file" mv "feeds.new" feeds rm "$datlinks_file" datserver_update_settings_template chown -R datserver:datserver /etc/datserver/feeds systemctl restart datserver fi } function change_updates_settings { if [ -f "$settings_updates_file" ]; then updates_enabled=$(awk -F ',' '{print $1}' < "$settings_updates_file") if [[ "$updates_enabled" != '0' && "$updates_enabled" != '1' ]]; then rm "$settings_updates_file" return fi updates_repo=$(awk -F ',' '{print $2}' < "$settings_updates_file") if [[ "$updates_repo" != *'.'* || "$updates_repo" != 'http'* || "$updates_repo" == *' '* || "$updates_repo" == *'$'* || "$updates_repo" == *'`'* ]]; then rm "$settings_updates_file" return fi updates_branch=$(awk -F ',' '{print $3}' < "$settings_updates_file") if [[ "$updates_branch" == 'http'* || "$updates_branch" == *' '* || "$updates_branch" == *'$'* || "$updates_branch" == *'`'* ]]; then rm "$settings_updates_file" return fi PROJECT_REPO='none' if [ "$updates_repo" ]; then PROJECT_REPO="$updates_repo" fi if grep -q 'PROJECT_REPO=' "$CONFIGURATION_FILE"; then sed -i "s|PROJECT_REPO=.*|PROJECT_REPO=$PROJECT_REPO|g" "$CONFIGURATION_FILE" else echo "PROJECT_REPO=$PROJECT_REPO" >> "$CONFIGURATION_FILE" fi STABLE_BRANCH= if [ "$updates_branch" ]; then STABLE_BRANCH="$updates_branch" fi if grep -q 'STABLE_BRANCH=' "$CONFIGURATION_FILE"; then sed -i "s|STABLE_BRANCH=.*|STABLE_BRANCH=$STABLE_BRANCH|g" "$CONFIGURATION_FILE" else echo "STABLE_BRANCH=$STABLE_BRANCH" >> "$CONFIGURATION_FILE" fi # change default checked state for radio button if [[ "$updates_enabled" == '1' ]]; then sed -i "s|value=\"1\">|value=\"1\" checked>|g" "$webadmin_install_dir/settings_updates.html" sed -i "s|value=\"0\" checked>|value=\"0\">|g" "$webadmin_install_dir/settings_updates.html" else sed -i "s|value=\"0\">|value=\"0\" checked>|g" "$webadmin_install_dir/settings_updates.html" sed -i "s|value=\"1\" checked>|value=\"1\">|g" "$webadmin_install_dir/settings_updates.html" fi # update variables within updates settings screen sed -i "s|name=\"updates_repo\".*|name=\"updates_repo\" value=\"$PROJECT_REPO\">|g" "$webadmin_install_dir/settings_updates.html" sed -i "s|name=\"updates_branch\".*|name=\"updates_branch\" value=\"$STABLE_BRANCH\">|g" "$webadmin_install_dir/settings_updates.html" # if we are updating from the web UI then disable any development branch if grep -q 'DEVELOPMENT_BRANCH=' "$CONFIGURATION_FILE"; then sed '/DEVELOPMENT_BRANCH=/d' "$CONFIGURATION_FILE" fi rm "$settings_updates_file" fi } function update_enable_ssh { if [ -f "$ssh_file" ]; then SSH_CONFIG='/etc/ssh/sshd_config' if ! grep -q 'PasswordAuthentication' $SSH_CONFIG; then echo 'PasswordAuthentication no' >> $SSH_CONFIG fi if grep -q '#PasswordAuthentication' $SSH_CONFIG; then sed -i "s|#PasswordAuthentication|PasswordAuthentication|g" $SSH_CONFIG fi if ! grep -q 'PasswordAuthentication no' $SSH_CONFIG; then sed -i "s|PasswordAuthentication.*|PasswordAuthentication no|g" $SSH_CONFIG fi ssh_active=$(awk -F ',' '{print $1}' < "$ssh_file") ADMIN_USERNAME=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [[ "$ssh_active" != '1' ]]; then # disable ssh access if [ -f "/home/$ADMIN_USERNAME/.ssh/authorized_keys" ]; then rm "/home/$ADMIN_USERNAME/.ssh/authorized_keys" fi iptables -D INPUT -p udp --dport "${SSH_PORT}" -j ACCEPT iptables -D INPUT -p tcp --dport "${SSH_PORT}" -j ACCEPT else # enable ssh access ssh_public_key=$(awk -F ',' '{print $2}' < "$ssh_file") if [ ${#ssh_public_key} -gt 20 ]; then if [[ "$ssh_public_key" == 'ssh-'* ]]; then if [ ! -d "/home/$ADMIN_USERNAME/.ssh" ]; then mkdir "/home/$ADMIN_USERNAME/.ssh" fi echo "$ssh_public_key" > "/home/$ADMIN_USERNAME/.ssh/authorized_keys" echo "" >> "/home/$ADMIN_USERNAME/.ssh/authorized_keys" chown -R "$ADMIN_USERNAME":"$ADMIN_USERNAME" "/home/$ADMIN_USERNAME/.ssh" iptables -A INPUT -p udp --dport "${SSH_PORT}" -j ACCEPT iptables -A INPUT -p tcp --dport "${SSH_PORT}" -j ACCEPT fi fi fi iptables-save > /etc/firewall.conf ip6tables-save > /etc/firewall6.conf systemctl restart ssh rm "$ssh_file" fi } function update_email_blocklists { FIREWALL_DOMAINS_OLD="$1" FIREWALL_DOMAINS_NEW="${1}.new" if [ -f "$FIREWALL_DOMAINS_OLD" ]; then # remove email blocks for d in /home/*/ ; do USERNAME=$(echo "$d" | awk -F '/' '{print $3}') if [[ $(is_valid_user "$USERNAME") == "1" ]]; then while read -r block_line; do if [ "$block_line" ]; then if [[ "$block_line" != *'@'* ]]; then # line is a domain name new_block_line="@${block_line}" block_line="${new_block_line}" fi # does not exist in the new version if ! grep -q "$block_line" "$FIREWALL_DOMAINS_NEW"; then "${PROJECT_NAME}-unignore" -u "$USERNAME" -e "$block_line" fi fi done < "$FIREWALL_DOMAINS_OLD" fi done fi # add email blocks for d in /home/*/ ; do USERNAME=$(echo "$d" | awk -F '/' '{print $3}') if [[ $(is_valid_user "$USERNAME") == "1" ]]; then while read -r block_line; do if [ "$block_line" ]; then if [[ "$block_line" != *'@'* ]]; then # line is a domain name new_block_line="@${block_line}" block_line="${new_block_line}" fi if [ -f "$FIREWALL_DOMAINS_OLD" ]; then # does not exist in the old version if ! grep -q "$block_line" "$FIREWALL_DOMAINS_OLD"; then "${PROJECT_NAME}-ignore" -u "$USERNAME" -e "$block_line" fi else "${PROJECT_NAME}-ignore" -u "$USERNAME" -e "$block_line" fi fi done < "$FIREWALL_DOMAINS_NEW" fi done } function update_email_muted_words { MUTED_WORDS_OLD="$1" MUTED_WORDS_NEW="${1}.new" muted_words_changed= if [ -f "$MUTED_WORDS_OLD" ]; then # remove email blocks for d in /home/*/ ; do USERNAME=$(echo "$d" | awk -F '/' '{print $3}') if [[ $(is_valid_user "$USERNAME") == "1" ]]; then while read -r block_line; do if [ "$block_line" ]; then # does not exist in the new version if ! grep -q "$block_line" "$MUTED_WORDS_NEW"; then "${PROJECT_NAME}-unignore" -u "$USERNAME" -a "$block_line" muted_words_changed=1 fi fi done < "$MUTED_WORDS_OLD" fi done fi # add email blocks for d in /home/*/ ; do USERNAME=$(echo "$d" | awk -F '/' '{print $3}') if [[ $(is_valid_user "$USERNAME") == "1" ]]; then while read -r block_line; do if [ "$block_line" ]; then if [ -f "$MUTED_WORDS_OLD" ]; then # does not exist in the old version if ! grep -q "$block_line" "$MUTED_WORDS_OLD"; then "${PROJECT_NAME}-ignore" -u "$USERNAME" -a "$block_line" muted_words_changed=1 fi else "${PROJECT_NAME}-ignore" -u "$USERNAME" -a "$block_line" muted_words_changed=1 fi fi done < "$MUTED_WORDS_NEW" fi done if [ $muted_words_changed ]; then if [ -f /etc/prosody/prosody.cfg.lua ]; then systemctl restart prosody fi fi } function update_blocklist { if [ -f "$blocklist_file" ]; then if [ -f "${FIREWALL_DOMAINS}.new" ]; then rm "${FIREWALL_DOMAINS}.new" fi touch "${FIREWALL_DOMAINS}.new" # create the prosody firewall file if [ -d /var/lib/prosody ]; then blacklisted_addresses_filename=/var/lib/prosody/blocked_addresses.txt if [ -f "${blacklisted_addresses_filename}.new" ]; then rm "${blacklisted_addresses_filename}.new" fi fi # add an extra line, otherwise the last line may not parse echo "" >> "$blocklist_file" blocked_lines_ctr=0 while read -r line; do if [ $blocked_lines_ctr -gt 1024 ]; then # This prevents someone copy-pasting a giant amount of text # into the blocklist. If you're legitimately blocking more # than this number then you probably have other problems to # think about and should consider whitelisting instead break fi blocked_lines_ctr=$((blocked_lines_ctr + 1)) if [ "$line" ]; then # remove leading and trailing spaces newline="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" line="$newline" if [[ "$line" == *'@'* ]]; then # blocked user # remove leading @ if [[ "$line" == '@'* ]]; then newline=${line:1} line="$newline" fi blocked_username=$(echo "$line" | awk -F '@' '{print $1}') if valid_username_characters "$blocked_username"; then blocked_domain=$(echo "$line" | awk -F '@' '{print $2}') if [[ "$blocked_domain" == *'.'* ]]; then if [ ${#blocked_domain} -gt 3 ]; then test_domain=$(echo "$blocked_domain" | tr -dc a-z0-9.-) if [[ "$blocked_domain" == "$test_domain" ]]; then blocked_address="${blocked_username}@${blocked_domain}" if ! grep -q "$blocked_address" "${FIREWALL_DOMAINS}.new"; then echo "${blocked_username}@${blocked_domain}" >> "${FIREWALL_DOMAINS}.new" # update the prosody firewall if [ -d /var/lib/prosody ]; then if ! grep -q "${blocked_username}@${blocked_domain}" "${blacklisted_addresses_filename}.new"; then echo "${blocked_username}@${blocked_domain}" >> "${blacklisted_addresses_filename}.new" fi fi fi fi fi fi fi else # blocked domain if [[ "$line" == *'.'* ]]; then blocked_domain="$line" test_domain=$(echo "$blocked_domain" | tr -dc a-z0-9.-) if [[ "$blocked_domain" == "$test_domain" ]]; then if [ ${#blocked_domain} -gt 3 ]; then if ! grep -q "$blocked_domain" "${FIREWALL_DOMAINS}.new"; then echo "$blocked_domain" >> "${FIREWALL_DOMAINS}.new" fi fi fi fi fi fi done < "$blocklist_file" # update the prosody firewall if [ -d /var/lib/prosody ]; then if [ -f "${blacklisted_addresses_filename}.new" ]; then cp "${blacklisted_addresses_filename}.new" "${blacklisted_addresses_filename}" rm "${blacklisted_addresses_filename}.new" else echo -n '' > "${blacklisted_addresses_filename}" fi chown prosody:prosody "${blacklisted_addresses_filename}" systemctl restart prosody fi update_email_blocklists "${FIREWALL_DOMAINS}" mv "${FIREWALL_DOMAINS}" "${FIREWALL_DOMAINS}.backup" mv "${FIREWALL_DOMAINS}.new" "${FIREWALL_DOMAINS}" rm "$blocklist_file" regenerate_blocklist fi } function update_muted_words { if [ -f "$muted_words_file" ]; then if [ -f "${MUTED_WORDS}.new" ]; then rm "${MUTED_WORDS}.new" fi touch "${MUTED_WORDS}.new" # add an extra line, otherwise the last line may not parse echo "" >> "$muted_words_file" blocked_lines_ctr=0 while read -r line; do if [ $blocked_lines_ctr -gt 1024 ]; then # This prevents someone copy-pasting a giant amount of text # into the blocklist. If you're legitimately blocking more # than this number then you probably have other problems to # think about and should consider whitelisting instead break fi blocked_lines_ctr=$((blocked_lines_ctr + 1)) if [ "$line" ]; then # remove leading and trailing spaces newline="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" line="$newline" if [ ${#line} -gt 1 ]; then blocked_words_str="$line" if ! grep -q "$blocked_words_str" "${MUTED_WORDS}.new"; then echo "$blocked_words_str" >> "${MUTED_WORDS}.new" fi fi fi done < "$muted_words_file" update_email_muted_words "${MUTED_WORDS}" mv "${MUTED_WORDS}" "${MUTED_WORDS}.backup" mv "${MUTED_WORDS}.new" "${MUTED_WORDS}" rm "$muted_words_file" regenerate_blocklist_muted_words fi } function import_translations { if [ -f "$translations_import_file" ]; then translations_language= if [ -f "translations_import.new" ]; then rm "translations_import.new" fi touch "translations_import.new" # add an extra line, otherwise the last line may not parse echo "" >> "$translations_import_file" import_lines_ctr=0 translation_lines_ctr=0 while read -r line; do if [ $import_lines_ctr -gt 2048 ]; then # This prevents someone copy-pasting a giant amount of text break fi if [ "$line" ]; then import_lines_ctr=$((import_lines_ctr + 1)) # remove leading and trailing spaces newline="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" line="$newline" if [ $import_lines_ctr -eq 1 ]; then translations_language="$line" fi if [ "$translations_language" ]; then if [[ "$line" == *'|'* ]]; then no_of_separators=$(echo "${line}" | awk -F '|' '{print NF-1}') # shellcheck disable=SC2086 if [ $no_of_separators -eq 1 ]; then echo "$line" >> "translations_import.new" translation_lines_ctr=$((translation_lines_ctr + 1)) fi fi fi fi done < "$translations_import_file" if [ "$translations_language" ]; then if [ $translation_lines_ctr -gt 100 ]; then local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ ! -d "$webadmin_install_dir/translations" ]; then mkdir "$webadmin_install_dir/translations" fi mv "translations_import.new" "$webadmin_install_dir/translations/${translations_language}.txt" chown -R www-data:www-data "$webadmin_install_dir/translations" # keep the imported translations if [ ! -f "$webadmin_install_dir/.keep_translations.txt" ]; then touch "$webadmin_install_dir/.keep_translations.txt" chown www-data:www-data "$webadmin_install_dir/.keep_translations.txt" fi fi fi if [ -f "translations_import.new" ]; then rm "translations_import.new" fi rm "$translations_import_file" fi } function change_default_domain { if [ -f "$default_domain_file" ]; then new_default_domain_name=$(cat "$default_domain_file") rm "$default_domain_file" # only applies to the standard server install, not onion ONION_ONLY=$(grep 'ONION_ONLY=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [[ "$ONION_ONLY" == 'no' ]]; then if [ "$new_default_domain_name" ]; then if [ ${#new_default_domain_name} -gt 5 ]; then if [[ "$new_default_domain_name" == *'.'* ]]; then # has the default domain changed ? DEFAULT_DOMAIN_NAME=$(grep 'DEFAULT_DOMAIN_NAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [[ "$DEFAULT_DOMAIN_NAME" != "$new_default_domain_name" ]]; then # set the new default domain within the config file if ! grep -q "NEW_DEFAULT_DOMAIN_NAME=" $CONFIGURATION_FILE; then echo "NEW_DEFAULT_DOMAIN_NAME=$new_default_domain_name" >> $CONFIGURATION_FILE else sed -i "s|NEW_DEFAULT_DOMAIN_NAME=.*|NEW_DEFAULT_DOMAIN_NAME=$new_default_domain_name|g" $CONFIGURATION_FILE fi # initiate an upgrade touch "$upgrade_file" fi fi fi fi fi fi } function create_scuttlebot_invite { if [ -f "$scuttlebot_file" ]; then if [ -d /etc/scuttlebot ]; then invite_string=$(su -c "/etc/scuttlebot/node_modules/.bin/sbot invite.create 1" - scuttlebot | sed 's/"//g') if [ ! "$invite_string" ]; then echo $'Unable to create scuttlebot invite' exit 36 fi current_invite=$(grep 'SCUTTLEBOT_INVITE=' "/root/${PROJECT_NAME}.cfg" | head -n 1 | sed 's|SCUTTLEBOT_INVITE=||g') sed -i "s|SCUTTLEBOT_INVITE=.*|SCUTTLEBOT_INVITE=${invite_string}|g" "/root/${PROJECT_NAME}.cfg" sed -i "s|$current_invite|$invite_string|g" "$webadmin_install_dir/app_scuttlebot.html" if [ ! -f /usr/local/bin/myqr ]; then echo -n "$invite_string" | qrencode -t PNG -o "$webadmin_install_dir/app_qrcode_scuttlebot.png" else myqr "$invite_string" -p /root/freedombone/img/android-app/scuttlebot.png -c -n "$webadmin_install_dir/app_qrcode_scuttlebot.png" fi echo -n "$invite_string" > /etc/scuttlebot/.current_invite.txt fi rm "$scuttlebot_file" fi } function update_bridges { if [ -f "$bridgeslist_file" ]; then if [ -f "/root/.webadmin_torbridges" ]; then rm "/root/.webadmin_torbridges" fi touch "/root/.webadmin_torbridges" if [ ! -f /usr/bin/obfs4proxy ]; then apt-get -yq install obfs4proxy fi bridge_type='obfs4' { echo 'ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy managed'; echo 'UseBridges 1'; } > /etc/torrc.d/bridges bridges_lines_ctr=0 while read -r line; do if [ $bridges_lines_ctr -gt 1024 ]; then # This prevents someone copy-pasting a giant amount of text # into the bridges list. break fi bridges_lines_ctr=$((bridges_lines_ctr + 1)) if [ "$line" ]; then # remove leading and trailing spaces newline="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" line="$newline" if [ ${#line} -gt 10 ]; then if [[ "$line" == '#'* ]]; then echo "$line" >> "/root/.webadmin_torbridges" else bridge_ip_address=$(echo "$line" | awk -F ':' '{print $1}') bridge_port=$(echo "$line" | awk -F ':' '{print $2}' | awk -F ' ' '{print $1}') bridge_key=$(echo "$line" | awk -F ' ' '{print $2}') if [[ "${bridge_ip_address}" == *"."* ]]; then if ! grep -q "Bridge $bridge_type ${bridge_ip_address}:${bridge_port} ${bridge_key}" /etc/torrc.d/bridges; then echo "Bridge $bridge_type ${bridge_ip_address}:${bridge_port} ${bridge_key}" >> /etc/torrc.d/bridges echo "${bridge_ip_address}:${bridge_port} ${bridge_key}" >> "/root/.webadmin_torbridges" fi fi fi fi fi done < "$bridgeslist_file" rm "$bridgeslist_file" regenerate_bridges systemctl restart tor fi } function update_email_proxy { # This allows outgoing email to be proxied through your ISP or another SMTP server if [ -f "$email_proxy_file" ]; then isp_smtp_domain=$(awk -F ',' '{print $1}' < "$email_proxy_file") isp_smtp_port=$(awk -F ',' '{print $2}' < "$email_proxy_file") isp_smtp_username=$(awk -F ',' '{print $3}' < "$email_proxy_file") isp_smtp_password=$(awk -F ',' '{print $4}' < "$email_proxy_file") rm "$email_proxy_file" email_smtp_proxy_through_isp "$isp_smtp_domain" "$isp_smtp_port" "$isp_smtp_username" "$isp_smtp_password" fi } function update_dynamic_dns { if [ -f "$dynamic_dns_file" ]; then ddns=$(awk -F ',' '{print $1}' < "$dynamic_dns_file") ddns_username=$(awk -F ',' '{print $2}' < "$dynamic_dns_file") ddns_password=$(awk -F ',' '{print $3}' < "$dynamic_dns_file") ddns_code=$(awk -F ',' '{print $4}' < "$dynamic_dns_file") ddns_is_valid= if [ "$ddns_username" ]; then if [ "$ddns_password" ]; then if [ ${#ddns_username} -gt 2 ]; then if [ ${#ddns_username} -lt 512 ]; then if [ ${#ddns_password} -gt 2 ]; then if [ ${#ddns_password} -lt 512 ]; then ddns_is_valid=1 fi fi fi fi fi fi if [ $ddns_is_valid ]; then /usr/local/bin/${PROJECT_NAME}-ddns "$ddns" "$ddns_username" "$ddns_password" if [ "$ddns_code" ]; then if [ ${#ddns_code} -gt 30 ]; then # if the whole cron line was pasted then parse that if [[ "$ddns_code" == *'freedns'* ]]; then if [[ "$ddns_code" == *'?'* && "$ddns_code" == *'='* ]]; then ddns_code=$(echo "$ddns_code" | awk -F '?' '{print $2}' | awk -F '=' '{print $1}') fi fi if grep -q "DEFAULT_DOMAIN_CODE=" "$CONFIGURATION_FILE"; then sed -i "s|DEFAULT_DOMAIN_CODE=.*|DEFAULT_DOMAIN_CODE=${ddns_code}|g" "$CONFIGURATION_FILE" else echo "DEFAULT_DOMAIN_CODE=${ddns_code}" >> "$CONFIGURATION_FILE" fi else ddns_code= fi fi regenerate_dynamic_dns "$ddns" "$ddns_username" "$ddns_password" "$ddns_code" fi rm "$dynamic_dns_file" fi } function webadmin_monitor_ip_changes { if [ -f "$webadmin_install_dir/dynamicdns.html" ]; then ONION_ONLY=$(grep 'ONION_ONLY=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [[ "$ONION_ONLY" == 'no' ]]; then webadmin_monitor_ip_ctr=$((webadmin_monitor_ip_ctr-1)) if [ $webadmin_monitor_ip_ctr -le 0 ]; then webadmin_monitor_ip_ctr=300 curr_ipv4=$(get_external_ipv4_address) if [ "$curr_ipv4" ]; then if [[ "$curr_ipv4" != "$webadmin_ipv4_address" ]]; then if [ "$webadmin_ipv4_address" ]; then # update dynamic dns if grep -q 'freedns' /etc/crontab; then DEFAULT_DOMAIN_CODE=$(grep 'DEFAULT_DOMAIN_CODE=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [ "$DEFAULT_DOMAIN_CODE" ]; then # shellcheck disable=SC2086 wget --no-check-certificate -O - https://freedns.afraid.org/dynamic/update.php?$DEFAULT_DOMAIN_CODE= >> /var/log/freedns_@_update.log 2>&1 & fi fi /usr/local/bin/${PROJECT_NAME}-notification -s "[${PROJECT_NAME}] Dynamic DNS" -m "IP address changed from $webadmin_ipv4_address to $curr_ipv4" & fi webadmin_ipv4_address="$curr_ipv4" sed -i "s|<p class=\"ipaddress\".*|<p class=\"ipaddress\" translate=\"no\">${curr_ipv4}</p>|g" "$webadmin_install_dir/dynamicdns.html" fi fi fi fi fi } function change_theme { if [ -f "$theme_file" ]; then bg_color=$(awk -F ',' '{print $1}' < "$theme_file") fg_color=$(awk -F ',' '{print $2}' < "$theme_file") if ! grep -q 'WEBADMIN_BACKGROUND_COLOR=' "/root/${PROJECT_NAME}.cfg"; then echo "WEBADMIN_BACKGROUND_COLOR=${bg_color}" >> "/root/${PROJECT_NAME}.cfg" else sed -i "s|WEBADMIN_BACKGROUND_COLOR=.*|WEBADMIN_BACKGROUND_COLOR=${bg_color}|g" "/root/${PROJECT_NAME}.cfg" fi if ! grep -q 'WEBADMIN_FOREGROUND_COLOR=' "/root/${PROJECT_NAME}.cfg"; then echo "WEBADMIN_FOREGROUND_COLOR=${fg_color}" >> "/root/${PROJECT_NAME}.cfg" else sed -i "s|WEBADMIN_FOREGROUND_COLOR=.*|WEBADMIN_FOREGROUND_COLOR=${fg_color}|g" "/root/${PROJECT_NAME}.cfg" fi web_admin_background_color rm "$theme_file" fi } function change_language { if [ -f "$language_file" ]; then language=$(cat "$language_file") local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/language_template.html" ]; then if grep -q "\"$language\"" "$webadmin_install_dir/language_template.html"; then if ! grep -q "DEFAULT_LANGUAGE=" "$CONFIGURATION_FILE"; then echo "DEFAULT_LANGUAGE=$language" >> "$CONFIGURATION_FILE" else sed -i "s|DEFAULT_LANGUAGE=.*|DEFAULT_LANGUAGE=$language|g" "$CONFIGURATION_FILE" fi /usr/bin/timeout $APP_INSTALL_TIMEOUT_SEC /usr/local/bin/${PROJECT_NAME}-language "${language}" > "$webadmin_install_dir/log.txt" # change the selected language cp "$webadmin_install_dir/language_template.html" "$webadmin_install_dir/language.html" sed -i "s|\"$language\" translate=\"yes\"|\"$language\" translate=\"yes\" selected|g" "$webadmin_install_dir/language.html" chown www-data:www-data "$webadmin_install_dir/language.html" fi fi rm "$language_file" fi } function update_system_monitor { if [ -f "$system_monitor_file" ]; then rm "$system_monitor_file" drives_list=$(df -h | grep "/dev/") test_drive=/dev/sda2 if [[ "$drives_list" != *"$test_drive"* ]]; then test_drive=/dev/sda1 if [[ "$drives_list" != *"$test_drive"* ]]; then test_drive=/dev/mmcblk0p2 if [[ "$drives_list" != *"$test_drive"* ]]; then test_drive=/dev/mmcblk0p1 fi fi fi cpu_usage=$(grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}' | awk -F '.' '{print $1}') disk_use=$(df -h | grep $test_drive) disk_use_percent='0%' disk_use_gb='0' disk_size_gb='0' if [[ "$disk_use" == *"$test_drive"* ]]; then disk_use_percent=$(df -h | grep $test_drive | tail -n 1 | awk -F ' ' '{print $5}') disk_use_gb=$(df -h | grep $test_drive | tail -n 1 | awk -F ' ' '{print $3}' | sed 's|G||g') disk_size_gb=$(df -h | grep $test_drive | tail -n 1 | awk -F ' ' '{print $2}' | sed 's|G||g') fi backup_disk_use_percent= backup_disk_use_gb= if [ -f "$DRIVES_BASELINE_FILE" ]; then backup_device=$(detect_connected_drives) if [ "$backup_device" ]; then backup_mount_drive "$backup_device" if [ $backup_drive_mounted ]; then backup_disk_use=$(df -h | grep "$backup_device") backup_disk_use_percent='0%' backup_disk_use_gb='0' backup_disk_size_gb='0' if [[ "$backup_disk_use" == *"$backup_device"* ]]; then backup_disk_use_percent=$(df -h | grep "$backup_device" | tail -n 1 | awk -F ' ' '{print $5}') backup_disk_use_gb=$(df -h | grep "$backup_device" | tail -n 1 | awk -F ' ' '{print $3}' | sed 's|G||g') backup_disk_size_gb=$(df -h | grep "$backup_device" | tail -n 1 | awk -F ' ' '{print $2}' | sed 's|G||g') fi fi backup_unmount_drive fi fi total_memory=$(free -m | grep "Mem:" | awk -F ' ' '{print $2}') total_memory_gb_integer=$((total_memory/100)) total_memory_gb='0' if [ ${#total_memory_gb_integer} -gt 1 ]; then #shellcheck disable=SC2001 total_memory_gb=$(echo "$total_memory_gb_integer" | sed 's/.$/.&/') else #shellcheck disable=SC2001 total_memory_gb=0$(echo "$total_memory_gb_integer" | sed 's/.$/.&/') fi used_memory=$(free -m | grep "Mem:" | awk -F ' ' '{print $3}') used_memory_percent=$((used_memory * 100 / total_memory)) used_memory_gb_integer=$((used_memory/100)) used_memory_gb='0' if [ ${#used_memory_gb_integer} -gt 1 ]; then #shellcheck disable=SC2001 used_memory_gb=$(echo "$used_memory_gb_integer" | sed 's/.$/.&/') else #shellcheck disable=SC2001 used_memory_gb=0$(echo "$used_memory_gb_integer" | sed 's/.$/.&/') fi cpu_temperature=0 if [ -f /sys/class/thermal/thermal_zone0/temp ]; then cpu_temp=$(cat /sys/class/thermal/thermal_zone*/temp | head -n 1) if [ "$cpu_temp" ]; then cpu_temperature=$((cpu_temp / 1000)) fi fi disk_io_speed=20 disk_io_speed_percent=10 if [ "$test_drive" ]; then disk_io_speed=$(hdparm -t $test_drive | awk -F '= ' '{print $2}' | awk -F ' ' '{print $1}' | tail -n 1 | awk -F '.' '{print $1}') if [ "$disk_io_speed" ]; then disk_io_speed_percent=$((disk_io_speed * 100 / 500)) if [ $disk_io_speed_percent -gt 100 ]; then disk_io_speed_percent=100 fi fi fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" #spectre-meltdown-checker --no-color > "$webadmin_install_dir/spectre.txt" #if [ -f "$webadmin_install_dir/spectre.txt" ]; then # spectre_vulnerabilities=$(grep "VULNERABLE" "$webadmin_install_dir/spectre.txt" | grep -vc "NOT ") #else spectre_vulnerabilities=0 #fi if [ -f "$webadmin_install_dir/system_monitor_template.html" ]; then cp "$webadmin_install_dir/system_monitor_template.html" "$webadmin_install_dir/system_monitor.html" # remove spectre warning # shellcheck disable=SC2086 if [ $spectre_vulnerabilities -eq 0 ]; then sed -i 's|images/spectre.png||g' "$webadmin_install_dir/system_monitor.html" if [ -f "$webadmin_install_dir/spectre.txt" ]; then rm "$webadmin_install_dir/spectre.txt" fi fi if [ "$cpu_usage" ]; then sed -i "s|<div name=\"cpuusage\" class=\"w3-container.*|<div name=\"cpuusage\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${cpu_usage}%\">${cpu_usage}%</div>|g" "$webadmin_install_dir/system_monitor.html" fi if [ "$disk_use_percent" ]; then sed -i "s|<div name=\"diskspace\" class=\"w3-container.*|<div name=\"diskspace\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:$disk_use_percent\">${disk_use_gb} / ${disk_size_gb}GB</div>|g" "$webadmin_install_dir/system_monitor.html" fi if [ "$backup_disk_use_gb" ]; then sed -i "s|<div name=\"backupspace\" class=\"w3-container.*|<div name=\"backupspace\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:$backup_disk_use_percent\">${backup_disk_use_gb} / ${backup_disk_size_gb}GB</div>|g" "$webadmin_install_dir/system_monitor.html" else sed -i "/\"backupspace\"/d" "$webadmin_install_dir/system_monitor.html" sed -i '/titletextbackupspace/d' "$webadmin_install_dir/system_monitor.html" fi sed -i "s|<div name=\"memory\" class=\"w3-container.*|<div name=\"memory\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${used_memory_percent}%\">${used_memory_gb} / ${total_memory_gb}GB</div>|g" "$webadmin_install_dir/system_monitor.html" if [ $cpu_temperature -gt 0 ]; then sed -i "s|<div name=\"cputemp\" class=\"w3-container.*|<div name=\"cputemp\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${cpu_temperature}%\">${cpu_temperature}C</div>|g" "$webadmin_install_dir/system_monitor.html" else sed -i "/\"cputemp\"/d" "$webadmin_install_dir/system_monitor.html" sed -i '/titletextcputemp/d' "$webadmin_install_dir/system_monitor.html" fi sed -i "s|<div name=\"diskio\" class=\"w3-container.*|<div name=\"diskio\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${disk_io_speed_percent}%\">${disk_io_speed} MB/s</div>|g" "$webadmin_install_dir/system_monitor.html" chown www-data:www-data "$webadmin_install_dir/system_monitor.html" fi fi } function update_app_settings { if [ ! -f "$appsettings_file" ]; then return fi settings_data=$(cat "$appsettings_file") rm "$appsettings_file" echo "$settings_data" > "$webadmin_install_dir/settingschange.txt" echo '' >> "$webadmin_install_dir/settingschange.txt" echo 'update_app_settings' >> "$webadmin_install_dir/settingschange.txt" if [[ "$settings_data" == *','* ]]; then app_name=$(echo "$settings_data" | awk -F ',' '{print $1}') echo "app_name: ${app_name}" >> "$webadmin_install_dir/settingschange.txt" if [ "$app_name" ]; then app_filename="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" echo "app_filename: ${app_filename}" >> "$webadmin_install_dir/settingschange.txt" if [ -f "$app_filename" ]; then app_function=$(echo "$settings_data" | awk -F ',' '{print $2}') echo "app_function: ${app_function}" >> "$webadmin_install_dir/settingschange.txt" if [ "$app_function" ]; then if grep -q "function ${app_name}_setting_${app_function} {" "$app_filename"; then app_value=$(echo "$settings_data" | awk -F ',' '{print $3}') echo "app_value: ${app_value}" >> "$webadmin_install_dir/settingschange.txt" echo "script: $appsettings_script" >> "$webadmin_install_dir/settingschange.txt" check_for_existing_processes $appsettings_script { echo "echo \"Beginning webadmin ${app_name} app settings change \$(date)\" >> $webadmin_install_dir/settingschange.txt"; echo "PROJECT_NAME=$PROJECT_NAME"; echo "source $app_filename"; echo "${app_name}_setting_${app_function} $app_value"; echo "chown www-data:www-data $webadmin_install_dir/settingschange.txt"; echo "exit 0"; } >> $appsettings_script chmod +x $appsettings_script # run in a separate process ./$appsettings_script & fi fi fi fi else echo 'No settings specified' >> "$webadmin_install_dir/settingschange.txt" chown www-data:www-data "$webadmin_install_dir/settingschange.txt" fi } # If the freedombone command is already running then kill its process #shellcheck disable=SC2009 install_process=$(ps a | grep '/usr/local/bin/freedombone -c' | grep -v 'grep') if [ "$install_process" ]; then if [[ "$install_process" != *'grep'* ]]; then install_pid=$(echo "$install_process" | awk -F ' ' '{print $1}') if [ "$install_pid" ]; then pkill -9 "$install_pid" fi fi fi # get the current install state if [ -f "$install_state_file" ]; then install_state=$(cat "$install_state_file") # shellcheck disable=SC2086 if [ $install_state -ne $INSTALL_STATE_COMMAND_SUCCESS ]; then if grep -q 'install_final' "$COMPLETION_FILE"; then install_state=$INSTALL_STATE_COMMAND_SUCCESS else chown www-data:www-data "$webadmin_install_dir/log.txt" # remove the setup file containing login details if [ -f "$setup_file" ]; then rm "$setup_file" fi if [ -f /etc/nginx/.webadminpasswd ]; then rm /etc/nginx/.webadminpasswd fi install_state=$INSTALL_STATE_FIRST_BOOT fi echo -n "$install_state" > "$install_state_file" fi else if grep -q 'install_final' "$COMPLETION_FILE"; then install_state=$INSTALL_STATE_COMMAND_SUCCESS else install_state=$INSTALL_STATE_FIRST_BOOT fi echo -n "$install_state" > "$install_state_file" fi while true do if [ -f /tmp/.upgrading ]; then sleep 2 else web_admin_setup_login if [ -d "$webadmin_install_dir" ]; then if [ -f "$setup_file" ]; then update_progress_bar before_setup_runs check_install_command_state after_setup_has_finished sleep 1 else if [ $install_state -eq $INSTALL_STATE_COMMAND_SUCCESS ]; then reset_shutdown change_updates_settings update_enable_ssh webadmin_factory_reset webadmin_change_password update_blocklist update_muted_words update_dynamic_dns webadmin_monitor_ip_changes update_system_monitor change_language change_theme backup_and_restore backup_and_restore_keys add_remove_users update_app_settings update_syncthing update_smolrss update_icecast update_koel update_dlna update_dat_links update_email_proxy import_translations webadmin_upgrade create_scuttlebot_invite install_apps_from_webadmin change_default_domain sleep 1 remove_apps_from_webadmin fi fi fi sleep 1 fi done exit 0