diff --git a/install.sh b/install.sh index 08fc68b61..8bd66777e 100755 --- a/install.sh +++ b/install.sh @@ -2796,7 +2796,7 @@ restore_prior_website_files() if [[ ${PRIOR_WEB_CONFIG_VERSION} < "${NEW_WEB_CONFIG_VERSION}" ]]; then # If different versions, then update the current one. update_old_website_config_file "${ALLSKY_WEBSITE_CONFIGURATION_FILE}" \ - "${PRIOR_WEB_CONFIG_VERSION}" "${NEW_WEB_CONFIG_VERSION}" "local" + "${PRIOR_WEB_CONFIG_VERSION}" "${NEW_WEB_CONFIG_VERSION}" else display_msg --log progress "${ITEM} (copying)" MSG="${ALLSKY_WEBSITE_CONFIGURATION_NAME}: Already current @ version ${NEW_WEB_CONFIG_VERSION}" diff --git a/remote_website_install.sh b/remote_website_install.sh index e2f5bd41a..6115f5646 100755 --- a/remote_website_install.sh +++ b/remote_website_install.sh @@ -4,6 +4,8 @@ # Install or upgrade a remote Allsky Website. +# TODO: handle interrupts like in install.sh + # shellcheck disable=SC2155 [[ -z ${ALLSKY_HOME} ]] && export ALLSKY_HOME="$( realpath "$( dirname "${BASH_ARGV0}" )" )" ME="$( basename "${BASH_ARGV0}" )" @@ -21,14 +23,15 @@ DISPLAY_MSG_LOG="${ALLSKY_LOGS}/${ME/.sh/}.log" # Config variables HAVE_NEW_CONFIG="false" -HAVE_OLD_CONFIG="false" +HAVE_PRIOR_CONFIG="false" HAVE_NEW_REMOTE_CONFIG="false" HAVE_REALLY_OLD_REMOTE_CONFIG="false" -CONFIG_TO_USE="" +CONFIG_TO_USE="" # which Website configuration file to use? CONFIG_MESSAGE="" +REMOTE_WEBSITE_EXISTS="false" # Dialog size variables -DIALOG_WIDTH=70 +DIALOG_WIDTH="$( tput cols )"; ((DIALOG_WIDTH -= 10 )) DIALOG_HEIGHT=25 # Remote connectivity variables @@ -38,19 +41,42 @@ REMOTE_HOST="$( settings ".REMOTEWEBSITE_HOST" "${ALLSKY_ENV}" )" REMOTE_PORT="$( settings ".REMOTEWEBSITE_PORT" "${ALLSKY_ENV}" )" REMOTE_PASSWORD="$( settings ".REMOTEWEBSITE_PASSWORD" "${ALLSKY_ENV}" )" REMOTE_DIR="$( settings ".remotewebsiteimagedir" "${SETTINGS_FILE}" )" -REMOTE_PROTOCOL="$( settings ".remotewebsiteprotocol" )" -WEBSITE_EXISTS="false" +REMOTE_PROTOCOL="$( settings ".remotewebsiteprotocol" "${SETTINGS_FILE}" )" +REMOTE_PROTOCOL="${REMOTE_PROTOCOL,,}" # convert to lowercase + +#### TODO: this script needs to support ALL protocols, not just *ftp*. +# When it does, remove this check. +if [[ ${REMOTE_PROTOCOL} != "sftp" && ${REMOTE_PROTOCOL} != "ftp" && ${REMOTE_PROTOCOL} != "ftps" ]]; then + echo -e "\n\n" + echo "************* NOTICE *************" + echo "This script currently only supports ftp protocols." + echo "Support for the '${REMOTE_PROTOCOL}' protocol will be added in" + echo "the first point release." + echo -e "\n" + echo "In the meantime, if you have an existing remote Allsky Website," + echo "it should continue to work." + echo -e "\n" + + exit 0 +fi # Titles for various dialogs -DIALOG_BACK_TITLE="Allsky Remote Website Installer" +# don't use: DIALOG_BACK_TITLE="Allsky Remote Website Installer" DIALOG_WELCOME_TITLE="Allsky Remote Website Installer" -DIALOG_PRE_CHECK="Pre Installation Checks" +DIALOG_PRE_CHECK="${DIALOG_WELCOME_TITLE} - Pre Installation Checks" DIALOG_INSTALL="Installing Remote Website" DIALOG_DONE="Remote Website Installation Completed" DIALOG_TITLE_LOG="Allsky Remote Website Installation Log" -# Old Allksy Website files that should be remoevd if they exist -OLD_FILES_TO_REMOVE=("config.js" "configuration.json" "virtualsky.json" "README.md" "myImages") +# Old Allksy Website files that should be removed if they exist. +OLD_CONFIG_NAME="config.js" +OLD_FILES_TO_REMOVE=( \ + "${OLD_CONFIG_NAME}" \ + "${ALLSKY_WEBSITE_CONFIGURATION_NAME}" \ + "getTime.php" \ + "virtualsky.json" \ + "README.md" \ + "myImages") ############################################## functions @@ -87,36 +113,42 @@ function press_any_key() read -r -n1 -s } -# Adds the remote Website URL to the dialog text. - -# TODO FIX: Eric thinks seeing the remote URL confusing. - +# Add a common heading to the dialog text. function add_dialog_heading() { local DIALOG_TEXT="${1}" + + ## We no longer add the remote URL but have left this code in case we want + ## to add something else in the future. + ## Only the: ITEM_TO_ADD=xxx line should need changing. + echo "${DIALOG_TEXT}" + return + if [[ ${TEXT_ONLY} == "true" ]]; then DIALOG_RED="${RED}" DIALOG_NORMAL="${NC}" fi - local PADDING=$(( ((DIALOG_WIDTH-6) - ${#REMOTE_URL}) / 2 )) - local URL=$(printf "%${PADDING}s%s" "" "${REMOTE_URL}") - - echo -e "\n${DIALOG_RED}${URL}${DIALOG_NORMAL}\n${DIALOG_TEXT}" + local ITEM_TO_ADD="${REMOTE_URL}" + local PADDING=$(( ((DIALOG_WIDTH-6) - ${#ITEM_TO_ADD}) / 2 )) + local ITEM_TO_ADD="$( printf "%${PADDING}s%s" "" "${ITEM_TO_ADD}" )" + + echo -e "\n${DIALOG_RED}${ITEM_TO_ADD}${DIALOG_NORMAL}\n${DIALOG_TEXT}" } # Displays the specified type of Dialog, or in text mode just displays the text. # ${1} - The box type -# ${2} - The backtitle for the dialog -# ${3} - The title for the dialog -# ${4} - The text to disply in the dialog -# ${5} - Optional additional arguments to dialog +# ${2} - The title for the dialog +# ${3} - The text to disply in the dialog +# ${4} - Optional additional arguments to dialog # # Return - 1 if the user selected "No"; 0 otherwise function display_box() { local DIALOG_TYPE="${1}" - local DIALOG_TEXT="${4}" + local DIALOG_TITLE="${2}" + local DIALOG_TEXT="${3}" + local MORE_ARGS="${4}" DIALOG_TEXT="$( add_dialog_heading "${DIALOG_TEXT}" )" if [[ ${TEXT_ONLY} == "true" ]]; then @@ -132,159 +164,208 @@ function display_box() return ${RET} fi - local BACK_TITLE="${2}" - local DIALOG_TITLE="${3}" - local MORE_ARGS="${5}" + # Don't use: it's redundant most of the time --backtitle "${DIALOG_BACK_TITLE}" \ # shellcheck disable=SC2086 dialog \ --colors \ - --backtitle "${BACK_TITLE}" \ --title "${DIALOG_TITLE}" \ ${MORE_ARGS} \ "${DIALOG_TYPE}" "${DIALOG_TEXT}" ${DIALOG_HEIGHT} ${DIALOG_WIDTH} return $? } -function display_info_box() -{ - display_box "--infobox" "${1}" "${2}" "${3}" -} - -function display_prompt_dialog() -{ - display_box "--yesno" "${1}" "${2}" "${3}" - # Returns - The exit code (0 - Yes, >0 No) -} - # Displays a file Dialog, or in text mode just displays the file. -# ${1} - The backtitle for the dialog -# ${2} - The title for the dialog -# ${3} - The filename to display +# ${1} - The title for the dialog +# ${2} - The filename to display # # Returns - Nothing function display_log_file() { - local FILENAME="${3}" + local DIALOG_TITLE="${1}" + local FILENAME="${2}" if [[ ${TEXT_ONLY} == "true" ]]; then cat "${FILENAME}" return fi - local BACK_TITLE="${1}" - local DIALOG_TITLE="${2}" dialog \ --clear \ --colors \ - --backtitle "${BACK_TITLE}" \ --title "${DIALOG_TITLE}" \ --textbox "${FILENAME}" 22 77 } -# Runs the pre installation checks. This function will determine the following: -# - Is there a remote Website -# - Which configuration file to use for the remote Website +# Runs the pre installation checks to determine the following: +# - Is there a remote Website? +# - Which configuration file to use for the remote Website? # # The configuration file to use is decided using the following, in order: # -# If there is a remote-configuration.json in the /config folder then use it. -# If there is a remote-configuration.json in the allsky-OLD/config folder then use it. -# Otherwise: -# If there is a remote Website with a configuration.json file then save it in /config. -# If there is a remote Website and it has an old configuration file (config.js) then -# create a new remote-configuration.json in /config. +# 1a. If ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE} exists, use it. +# +# 1b. If ${PRIOR_REMOTE_WEBSITE_CONFIGURATION_FILE} exists, +# copy it to ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE} and use it. +# +# 2a. If there's a remote Website with a ${ALLSKY_WEBSITE_CONFIGURATION_NAME} file, +# save it locally as ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE} and use it. +# +# 2b. If there is a remote Website with an old-style configuration file (${OLD_CONFIG_NAME}), +# create a NEW ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE} and use it. +# Don't bother trying to convert from old-style files. function pre_install_checks() { + display_msg --logonly info "Start pre installation checks." + local MSG="" - local DIALOG_TEXT="\nRunning pre installation checks." - DIALOG_TEXT+="\n\nPlease wait as this can take a few minutes to complete.\n\n" + local DIALOG_TEXT DT + DIALOG_TEXT="\nWelcome to the Allsky Remote Website Installer!\n\n" + DIALOG_TEXT+="\nRunning pre installation checks.\n\n" - DIALOG_TEXT+="\n1 - Checking for local files" - display_info_box "${DIALOG_BACK_TITLE}" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" - display_msg --logonly info "Start pre installation checks." + DIALOG_TEXT+="\n1 - Checking for remote Website configuration file on Pi: " + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" if [[ -f ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE} ]]; then - MSG="Found current remote configuration file: ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}." + # 1a. + DT="FOUND" + MSG="Found ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}." display_msg --logonly info "${MSG}" HAVE_NEW_CONFIG="true" - fi - if [[ -f ${PRIOR_REMOTE_WEBSITE_CONFIGURATION_FILE} ]]; then - MSG="Found -OLD configuration file: ${PRIOR_REMOTE_WEBSITE_CONFIGURATION_FILE}." +### FIX / TODO: Should this be used? +# During Allsky upgrades, if the OLD directory exists users are asked if +# it should be used. If "yes", then the prior remote Website config file was +# copied to the new Allsky, so 1a should match. +# If the user answered "no", don't use OLD Allsky, we probably shouldn't either. + elif [[ -f ${PRIOR_REMOTE_WEBSITE_CONFIGURATION_FILE} ]]; then + # 1b. + DT="FOUND ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_NAME} in '${PRIOR_CONFIG_DIR}'" + MSG="Found ${PRIOR_REMOTE_WEBSITE_CONFIGURATION_FILE}." display_msg --logonly info "${MSG}" - HAVE_OLD_CONFIG="true" - fi - - DIALOG_TEXT+="\n2 - Checking if remote Website exists" - display_info_box "${DIALOG_BACK_TITLE}" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + HAVE_PRIOR_CONFIG="true" - check_if_website_exists # Sets ${WEBSITE_EXISTS} - if [[ ${WEBSITE_EXISTS} == "true" ]]; then - DIALOG_TEXT+="\n3 - Checking for remote Website configuration file" - display_info_box "${DIALOG_BACK_TITLE}" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" - local NEW_CONFIG_FILES=("configuration.json") - if check_if_files_exist "${REMOTE_URL}" "false" "${NEW_CONFIG_FILES[@]}" ; then + else + DT="NOT FOUND" + display_msg --logonly info "No local config files found." + fi + DIALOG_TEXT+="${DT}." + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + + DIALOG_TEXT+="\n2 - Checking for existing remote Website: " + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + local INDENT=" " + REMOTE_WEBSITE_EXISTS="$( check_if_website_exists )" + if [[ ${REMOTE_WEBSITE_EXISTS} == "true" ]]; then + + # If we didn't find a remote Website configuration file on the Pi, + # it's "should be" an old-style Website since the user wasn't + # using the WebUI to configure it. + + DIALOG_TEXT+="FOUND." + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + + # 2a. + DIALOG_TEXT+="\n${INDENT}* Checking it for new-style configuration file: " + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + local NEW_CONFIG_FILES=("${ALLSKY_WEBSITE_CONFIGURATION_NAME}") + if check_if_files_exist "${REMOTE_URL}" "or" "${NEW_CONFIG_FILES[@]}" ; then HAVE_NEW_REMOTE_CONFIG="true" - MSG="Found current configuration file on the remote server." + DIALOG_TEXT+="Found." + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + MSG="Found a current configuration file on the remote server." display_msg --logonly info "${MSG}" + else + # 2b. + DIALOG_TEXT+="Not found." + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + + DIALOG_TEXT+="\n${INDENT}* Checking it for old-style configuration file:" + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + local REALLY_OLD_CONFIG_FILES=("${OLD_CONFIG_NAME}") + if check_if_files_exist "${REMOTE_URL}" "or" "${REALLY_OLD_CONFIG_FILES[@]}" ; then + HAVE_REALLY_OLD_REMOTE_CONFIG="true" + DT="FOUND" + MSG="Found old-style ${OLD_CONFIG_NAME} file on the remote Website." + display_msg --logonly info "${MSG}" + else + # This "shouldn't" happen - the remote Website should have SOME type + # of configuration file. + DT="NOT FOUND" + fi + DIALOG_TEXT+="${DT}." + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" fi - - DIALOG_TEXT+="\n4 - Checking for old-style remote Website configuration file" - display_info_box "${DIALOG_BACK_TITLE}" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" - local REALLY_OLD_CONFIG_FILES=("config.js") - if check_if_files_exist "${REMOTE_URL}" "false" "${REALLY_OLD_CONFIG_FILES[@]}" ; then - HAVE_REALLY_OLD_REMOTE_CONFIG="true" - MSG="Found old-format config.js file on the remote Website." - display_msg --logonly info "${MSG}" + else + # No remote Website found. + DIALOG_TEXT+="NOT FOUND." + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + + if [[ ${HAVE_NEW_CONFIG} == "true" || ${HAVE_PRIOR_CONFIG} == "true" ]]; then + DIALOG_TEXT+="${DIALOG_RED}" + DIALOG_TEXT+="\n${INDENT}WARNING: a remote configuration file exists" + DIALOG_TEXT+="\n${INDENT}but a remote Website wasn't found." + DIALOG_TEXT+="\n${INDENT}What is the configuration file for?" + DIALOG_TEXT+="${DIALOG_NORMAL}" + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" fi + fi if [[ ${HAVE_NEW_CONFIG} == "true" ]]; then - MSG="Using the local remote configuration file" if [[ ${HAVE_NEW_REMOTE_CONFIG} == "true" ]]; then - MSG+=", a remote configuration file was found but using the local version instead" + MSG="A remote configuration file was found but using the local version instead." + else + MSG="Using the local remote configuration file (no remote file found)." fi - display_msg --logonly info "${MSG}." - CONFIG_TO_USE="current" + display_msg --logonly info "${MSG}" + CONFIG_TO_USE="local" # it may be old or current format CONFIG_MESSAGE="the current remote" - elif [[ ${HAVE_OLD_CONFIG} == "true" ]]; then - MSG="Using the -OLD configuration file; placeholders will be updated." + elif [[ ${HAVE_PRIOR_CONFIG} == "true" ]]; then + local B="$( basename "${PRIOR_ALLSKY_DIR}" )" + MSG="Using the ${B} configuration file." display_msg --logonly info "${MSG}" - CONFIG_TO_USE="old" - CONFIG_MESSAGE="the $( basename "${PRIOR_ALLSKY_DIR}" )" + CONFIG_TO_USE="prior" # it may be old or current format + CONFIG_MESSAGE="the ${B}" - elif [[ ${WEBSITE_EXISTS} == "true" ]]; then - if [[ ${HAVE_NEW_REMOTE_CONFIG} == "true" ]]; then - MSG="Using new format Website configuration file on the remote Website;" - MSG+=" it will be downloaded and saved locally." - display_msg --logonly info "${MSG}" - CONFIG_TO_USE="remotenew" - CONFIG_MESSAGE="the remote Website's" - else - if [[ ${HAVE_REALLY_OLD_REMOTE_CONFIG} == "true" ]]; then - MSG="Old config.js found." - MSG+=" Creating a new configuration file that the user must manually update." - display_msg --logonly info "${MSG}" - CONFIG_TO_USE="remotereallyold" - CONFIG_MESSAGE="a new" - fi - fi - fi + elif [[ ${HAVE_NEW_REMOTE_CONFIG} == "true" ]]; then + MSG="Using new-style Website configuration file on the remote Website;" + MSG+=" it will be downloaded and saved locally." + display_msg --logonly info "${MSG}" + CONFIG_TO_USE="remoteNew" + CONFIG_MESSAGE="the remote Website's" + + elif [[ ${HAVE_REALLY_OLD_REMOTE_CONFIG} == "true" ]]; then + MSG="Old ${OLD_CONFIG_NAME} found." + MSG+=" Creating a new configuration file that the user must manually update." + display_msg --logonly info "${MSG}" + CONFIG_TO_USE="remoteReallyOld" + CONFIG_MESSAGE="a new" - if [[ -z ${CONFIG_TO_USE} ]]; then + else MSG="Unable to determine the configuration file to use. A new one will be created." display_msg --logonly info "${MSG}" CONFIG_TO_USE="new" fi - check_connectivity + DIALOG_TEXT+="\n * Checking ability to upload to it: " + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + display_msg --logonly info "Checking remote Website connectivity." + local ERR="$( check_connectivity )" + if [[ -z ${ERR} ]]; then + DIALOG_TEXT+="PASSED." + display_box "--infobox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + show_debug_message "The remote Website connectivity test succeeded." + else + local ERROR_MSG="\nERROR: The remote Website connectivity check failed." + display_aborted "${ERROR_MSG}" "${ERR}" + fi display_msg --logonly info "Completed pre installation checks." # Prompt the user to continue. This is so they can see the above messages. DIALOG_TEXT+="\n\n\n${DIALOG_UNDERLINE}Press OK to continue${DIALOG_NORMAL}" - display_box "--msgbox" "${DIALOG_BACK_TITLE}" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" + display_box "--msgbox" "${DIALOG_PRE_CHECK}" "${DIALOG_TEXT}" } # Displays the welcome dialog indicating what steps will be taken @@ -297,23 +378,21 @@ function display_welcome() if [[ ${AUTO_CONFIRM} == "false" ]]; then display_msg --logonly info "Displaying the welcome dialog." - local DIALOG_MSG="\n\ - Welcome to the Allsky Remote Website Installer!\n\n\ - This script will perform the following tasks:\n\n\ + local DIALOG_TEXT="\n\ + This script will now:\n\n\ \ - 1) Check the remote Website connectivity - PASSED\n\ - 2) Use ${CONFIG_MESSAGE} configuration file\n\ - 3) Upload the remote Website code\n\ - 4) Upload the remote Website configuration file\n\ - 5) Enable the remote Website\n\n\ + 1) Use ${CONFIG_MESSAGE} configuration file.\n\ + 2) Upload the new remote Website code.\n\ + 3) Upload the remote Website configuration file.\n\ + 4) Enable the remote Website.\n\n\ \ - ${DIALOG_RED}WARNING:${DIALOG_NORMAL}\n\ - - This will overwrite files on the remote server, and\n\ - - REMOVE any old Allsky files on the remote server.\n\n\n\ + ${DIALOG_RED}WARNING! This will:${DIALOG_NORMAL}\n\ + - Overwrite the old Allsky web files on the remote server.\n\ + - Remove any old Allsky files from the remote server.\n\n\n\ ${DIALOG_UNDERLINE}Are you sure you wish to continue?${DIALOG_NORMAL}" - if ! display_prompt_dialog "${DIALOG_BACK_TITLE}" "${DIALOG_WELCOME_TITLE}" "${DIALOG_MSG}" ; then - display_aborted "--user" "at the Welcome dialog" "false" + if ! display_box "--yesno" "${DIALOG_WELCOME_TITLE}" "${DIALOG_TEXT}" ; then + display_aborted "--user" "at the Welcome dialog" "" fi else display_msg --logonly info "Ignored welcome prompt as auto confirm option specified." @@ -322,7 +401,7 @@ function display_welcome() # Displays the aborted dialog. This is used when an error is encountered or the user cancels. # ${1} - Extra text to display in the dialog -# ${2} - "true"/"false" - Flag to indicate if the user should be prompted to show the installation log +# ${2} - Error message (or "" if no error) function display_aborted() { if [[ ${1} == "--user" ]]; then @@ -332,23 +411,24 @@ function display_aborted() local ABORT_MSG="INSTALLATION ABORTED" fi local EXTRA_TEXT="${1}" - local SHOW_LOG="${2}" - - display_msg --logonly info "${ABORT_MSG} at $( date ) ${EXTRA_TEXT}.\n" - local ERROR_MSG="\nThe installation of the remote Website was aborted ${EXTRA_TEXT}." - - if [[ ${SHOW_LOG} == "true" ]]; then -# TODO: Instead of displaying the log file, which is very detailed, -# how about if we tell the user to attach the log file to any GitHub message they post? - MSG="${ERROR_MSG}\n\n" - MSG+="${DIALOG_UNDERLINE}Would you like to view the installation log?${DIALOG_NORMAL}" - if display_prompt_dialog "${DIALOG_BACK_TITLE}" "${DIALOG_INSTALL}" "${MSG}" ; then - display_log_file "${DIALOG_BACK_TITLE}" "${DIALOG_TITLE_LOG}" "${DISPLAY_MSG_LOG}" + local ERROR_MSG="${2}" + + display_msg --logonly info "${ABORT_MSG} ${EXTRA_TEXT}.\n" + local MSG="\nInstallation of the remote Website aborted ${EXTRA_TEXT}." + + if [[ -n ${ERROR_MSG} ]]; then + local DIALOG_PROMPT="${MSG}\n\n" + DIALOG_PROMPT+="${DIALOG_UNDERLINE}Would you like to view the error message?${DIALOG_NORMAL}" + if display_box "--yesno" "${DIALOG_INSTALL}" "${DIALOG_PROMPT}" ; then + display_box "--msgbox" "${DIALOG_TITLE_LOG}" "${ERROR_MSG}" "--scrollbar" +if false; then + display_log_file "${DIALOG_TITLE_LOG}" "${DISPLAY_MSG_LOG}" +fi fi fi clear # Gets rid of background color from last 'dialog' command. - display_msg info "${ERROR_MSG}" + # Not needed: display_msg info "${ERROR_MSG}" exit 1 } @@ -361,42 +441,36 @@ function display_complete() if [[ ${CONFIG_TO_USE} == "new" ]]; then EXTRA_TEXT="\nA new configuration file was created for your remote Website." EXTRA_TEXT+="${E}" - elif [[ ${CONFIG_TO_USE} == "remotereallyold" ]]; then + elif [[ ${CONFIG_TO_USE} == "remoteReallyOld" ]]; then EXTRA_TEXT="\nYou have a very old remote Allsky Website so a new configuration file was created." EXTRA_TEXT+="${E}" fi - display_msg --logonly info "INSTALLATON COMPLETED at $( date ).\n" + display_msg --logonly info "INSTALLATION COMPLETED.\n" local DIALOG_TEXT="\n\ - The installation of the remote Website is complete.\n\n\ - Please use the WebUI's 'Editor' page to manage any changes to your Website.${EXTRA_TEXT}" - display_box "--msgbox" "${DIALOG_BACK_TITLE}" "${DIALOG_DONE}" "${DIALOG_TEXT}" + The installation of the remote Website is complete\n\ + and the remote Website should be working.\n\n\ + Please check it.\n\n\ + Use the WebUI's 'Editor' page to change settings for your Website.${EXTRA_TEXT}" + display_box "--msgbox" "${DIALOG_DONE}" "${DIALOG_TEXT}" clear # Gets rid of background color from last 'dialog' command. display_msg info "\nEnjoy your remote Allsky Website!\n" } -# Check connectivity to the remote Website. +# Check connectivity to the remote Website by trying to upload a file to it. +# Return "" for success, else the error message. function check_connectivity() { local TEST_FILE="${ME}.txt" + local ERR - display_msg --logonly info "Checking remote Website connectivity." if ERR="$( "${ALLSKY_SCRIPTS}/testUpload.sh" --website --silent --file "${TEST_FILE}" 2>&1 )" ; then - local MSG="The remote Website connectivity test succeeded." - display_msg --logonly info "${MSG}" remove_remote_file "${TEST_FILE}" "do not check" + echo "" else - local ERROR_MSG="\nERROR: The remote Website connectivity check failed." - ERROR_MSG+="\n\nPlease check the 'Websites and Remote Server Settings' section of the WebUI.\n\n\ - HOST: ${REMOTE_HOST}\n\ - PROTOCOL: ${REMOTE_PROTOCOL}\n\ - USER: ${REMOTE_USER}\n\ - REMOTE FOLDER: ${REMOTE_DIR}\n\n\ - ${ERR}" - - display_aborted "${ERROR_MSG}" "true" + echo "${ERR}" fi } @@ -408,62 +482,91 @@ function show_debug_message() fi } +# Update a Website config file if it's an old version. +function update_old() +{ + local FILE="${1}" + + local PRIOR_VERSION="$( settings ".${WEBSITE_CONFIG_VERSION}" "${FILE}" )" + local NEW_VERSION="$( settings ".${WEBSITE_CONFIG_VERSION}" "${REPO_WEBCONFIG_FILE}" )" + if [[ ${PRIOR_VERSION} < "${NEW_VERSION}" ]]; then + # Old version, so update to format of the current version. + update_old_website_config_file "${FILE}" "${PRIOR_VERSION}" "${NEW_VERSION}" + return 0 + fi + return 1 +} + # Creates the remote Website configuration file if needed. # See 'pre_install_checks' for details on which configuration file is used. function create_website_config() { - local MSG="\nCreating configuration file from ${CONFIG_MESSAGE}" - display_info_box "${DIALOG_BACK_TITLE}" "${DIALOG_INSTALL}" "${MSG}" - display_msg --logonly info "Creating remote Website configuration file" - - if [[ ${CONFIG_TO_USE} == "new" || ${CONFIG_TO_USE} == "remotereallyold" ]]; then - # We need a new config file so copy it from the repo and replace as many - # of the placeholders as we can - DEST_FILE="${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" + local MSG="Creating configuration file from ${CONFIG_MESSAGE}" + display_msg --logonly info "${MSG}" + + if [[ ${CONFIG_TO_USE} == "new" || ${CONFIG_TO_USE} == "remoteReallyOld" ]]; then + # Need a new config file so copy it from the repo and replace as many + # placeholders as we can. + local DEST_FILE="${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" cp "${REPO_WEBCONFIG_FILE}" "${DEST_FILE}" replace_website_placeholders "remote" - MSG="Created a new ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_NAME} from repo and updated placeholders." + + MSG="Created a new ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_NAME}" + MSG+=" from repo and updated placeholders." display_msg --logonly info "${MSG}" - elif [[ ${CONFIG_TO_USE} == "current" ]]; then - # Use the current config file so do nothing - MSG="Using existing ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_NAME} so nothing created." + elif [[ ${CONFIG_TO_USE} == "local" ]]; then + # Using the remote config file on the Pi which may be new or old format. + MSG="Using existing ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_NAME}" + if update_old "${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" ; then + MSG+=" and converting to newest format." + fi display_msg --logonly info "${MSG}" - elif [[ ${CONFIG_TO_USE} == "old" ]]; then - # Use the config file from allsky-OLD, copy it and replace as many of the placeholders as we can + elif [[ ${CONFIG_TO_USE} == "prior" ]]; then + # Use the config file from the prior Allsky, replacing as many placeholders as we can. + # If the file is an older version, convert to the newest format. cp "${PRIOR_REMOTE_WEBSITE_CONFIGURATION_FILE}" "${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" replace_website_placeholders "remote" - MSG="Copying ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_NAME} from the" - MSG+=" $( basename "${PRIOR_ALLSKY_DIR}" ) directory and updating placeholders." + update_old "${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" + + MSG="Copied ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_NAME} from the" + MSG+=" $( basename "${PRIOR_ALLSKY_DIR}" ) directory and updated placeholders." display_msg --logonly info "${MSG}" - elif [[ ${CONFIG_TO_USE} == "remotenew" ]]; then - # Use the new remote config file since none were found locally - if wget -O "${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" "${REMOTE_URL}/${ALLSKY_WEBSITE_CONFIGURATION_FILE}" ; then + elif [[ ${CONFIG_TO_USE} == "remoteNew" ]]; then + # Use the new remote config file since none were found locally. + # Replace placeholders and convert it to the newest format. + # Remember that the remote file name is different than what we store on the Pi. + if ERR="$( wget -O "${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" "${REMOTE_URL}/${ALLSKY_WEBSITE_CONFIGURATION_FILE}" 2>&1 )"; then replace_website_placeholders "remote" - MSG="Downloading ${ALLSKY_WEBSITE_CONFIGURATION_FILE} from ${REMOTE_URL}," - MSG+=" and creating a new ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}." + update_old "${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" + + MSG="Downloaded ${ALLSKY_WEBSITE_CONFIGURATION_FILE} from ${REMOTE_URL}," + MSG+=" to ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}." display_msg --logonly info "${MSG}" else - MSG="Failed to download ${ALLSKY_WEBSITE_CONFIGURATION_FILE} from ${REMOTE_URL}" - display_aborted "${MSG}" "true" + # This "shouldn't" happen since we either already checked the file exists, + # or we uploaded it. + MSG="Failed to download ${ALLSKY_WEBSITE_CONFIGURATION_FILE} from ${REMOTE_URL}." + MSG+=" Where did it go?" + display_aborted "${MSG}" "${ERR}" fi fi } # Check if a remote file, or array of files, exist. # ${1} - The base url -# ${2} - "true"/"false" If true then all files must exist, if "false" then any of the files can exist. +# ${2} - "and"/"or" If "and" then all files must exist, if "or" then any of the files can exist. # ${3}... - the files # # Returns - 0 if the file(s) exist, 1 if ANY file doesn't exist. function check_if_files_exist() { local URL="${1}" - local AND="${2}" + local AND_OR="${2}" shift 2 - local RESULT=1 + local RET_CODE=1 for FILE in "$@"; do url="${URL}/${FILE}" @@ -472,16 +575,16 @@ function check_if_files_exist() local PRE_MSG="File ${FILE} ${url}" if [[ ${HTTP_STATUS} == "200" ]] ; then show_debug_message "${PRE_MSG} exists on the remote server" - RESULT=0 + RET_CODE=0 else show_debug_message "${PRE_MSG} does not exists on the remote server" - if [[ ${AND} == "true" ]]; then + if [[ ${AND_OR} == "and" ]]; then return 1 fi fi done - return ${RESULT} + return ${RET_CODE} } # Deletes a file from the remote server. @@ -495,17 +598,22 @@ function remove_remote_file() local CHECK="${2}" if [[ ${CHECK} == "check" ]]; then - if ! check_if_files_exist "${REMOTE_URL}" "false" "${FILENAME}" ; then + if ! check_if_files_exist "${REMOTE_URL}" "or" "${FILENAME}" ; then show_debug_message "===== not on server" return fi fi -# TODO: FIX: This assumes ftp is used to upload files -# TODO: upload.sh should accept "--remove FILE" option. - local CMDS="cd '${REMOTE_DIR}' ; rm -r '${FILENAME}' ; bye" - local ERR="$( lftp -u "${REMOTE_USER},${REMOTE_PASSWORD}" "${REMOTE_PORT}" "${REMOTE_PROTOCOL}://${REMOTE_HOST}" -e "${CMDS}" 2>&1 )" +# TODO: This assumes ftp is used to upload files +# upload.sh should accept "--remove FILE" option. + local CMDS="" ERR + [[ -n ${REMOTE_DIR} ]] && CMDS="cd '${REMOTE_DIR}' ;" + CMDS+=" rm -r '${FILENAME}' ; bye" + ERR="$( lftp -u "${REMOTE_USER},${REMOTE_PASSWORD}" \ + "${REMOTE_PORT}" \ + "${REMOTE_PROTOCOL}://${REMOTE_HOST}" \ + -e "${CMDS}" 2>&1 )" if [[ $? -eq 0 ]] ; then MSG="Deleted remote file '${FILENAME}'" else @@ -515,75 +623,104 @@ function remove_remote_file() display_msg --logonly info "${MSG}" } -# Check if a remote Website exists. The check is done by looking for the following files: -# -# If any of the ${CONFIG_FILES} files exist and -# all of the ${WEBSITE_FILES} exist then assume we have a remote Website. +# Check if a remote Website exists. +# The check is done by looking for the following files: +# If any of the ${CONFIG_FILES} files exist AND +# all of the ${WEBSITE_FILES} exist then assume we have a remote Website. # -# Returns - Nothing, but set the global variable ${WEBSITE_EXISTS}. +# Returns - echo "true" if it exists, else "false" function check_if_website_exists() { - local CONFIG_FILES=("config.json" "configuration.json" "remote_configuration.json") + local CONFIG_FILES=("${OLD_CONFIG_NAME}" "${ALLSKY_WEBSITE_CONFIGURATION_NAME}") local WEBSITE_FILES=("index.php" "functions.php") - if check_if_files_exist "${REMOTE_URL}" "false" "${CONFIG_FILES[@]}" ; then - show_debug_message "Found remote website config file" + if check_if_files_exist "${REMOTE_URL}" "or" "${CONFIG_FILES[@]}" ; then + show_debug_message "Found a remote Website config file" if check_if_files_exist "${REMOTE_URL}" "and" "${WEBSITE_FILES[@]}" ; then - display_msg --logonly info "Found remote Allsky Website at ${REMOTE_URL}" - WEBSITE_EXISTS="true" - return + display_msg --logonly info "Found a remote Allsky Website at ${REMOTE_URL}" + echo "true" + return 0 fi fi - WEBSITE_EXISTS="false" + echo "false" + return 1 } -# Uploads the Website code from ${ALLSKY_WEBSITE} and removes any old -# Allsky files that are no longer needed. +# Uploads the Website code from ${ALLSKY_WEBSITE} and removes any old Allsky +# files that are no longer used. function upload_remote_website() { if [[ ${SKIP_UPLOAD} == "true" ]]; then - display_msg --logonly info "Skipping upload as --skipupload provided on command line.\n" + display_msg --logonly info "Skipping upload per user request.\n" return fi - local EXTRA_TEXT="" - local EXCLUDE_FOLDERS="" + local EXTRA_TEXT="" EXCLUDE_FOLDERS="" MSG if [[ -n ${REMOTE_PORT} ]]; then REMOTE_PORT="-p ${REMOTE_PORT}" fi - local MSG="Starting upload to the remote Website" - if [[ ${WEBSITE_EXISTS} == "true" ]]; then + MSG="Starting upload to the remote Website" + [[ -n ${REMOTE_DIR} ]] && MSG+=" in ${REMOTE_DIR}" + if [[ ${REMOTE_WEBSITE_EXISTS} == "true" ]]; then + + # Don't upload images if the remote Website exists (we assume it already + # has the images). + # However, we must upload the index.php files. EXCLUDE_FOLDERS="--exclude keograms --exclude startrails --exclude videos" - MSG+=", excluding videos, startrails, and keograms" + +# FIX: the --include doesn't work - the files aren't uploaded. +# Do we need to do a second lftp mirror to upload them? + EXCLUDE_FOLDERS+=" --include keograms/index.php" + EXCLUDE_FOLDERS+=" --include startrails/index.php" + EXCLUDE_FOLDERS+=" --include videos/index.php" + MSG+=" (without videos, images, and their thumbnails)." fi display_msg --logonly info "${MSG}${EXTRA_TEXT}." - MSG="\n${MESSAGE}\n\nPlease wait as uploading files could take several minutes..." - display_info_box "${DIALOG_BACK_TITLE}" "${DIALOG_INSTALL}" "${MSG}" - - { -# TODO: upload.sh should have a "--mirror directory" option. + MSG="\n${MSG}\n\nThis may take several minutes..." + display_box "--infobox" "${DIALOG_INSTALL}" "${MSG}" + +# TODO: upload.sh should have a "--mirror from_directory to_directory" option. # This would also fix the problem that we're assuming the "ftp" protocol is used. - # shellcheck disable=SC2086 - lftp -u "${REMOTE_USER},${REMOTE_PASSWORD}" ${REMOTE_PORT} "${REMOTE_PROTOCOL}://${REMOTE_HOST}" -e " - lcd '${ALLSKY_WEBSITE}' - cd '${REMOTE_DIR}' - set dns:fatal-timeout 10 - set net:max-retries 2 - set net:timeout 10 - mirror --reverse --verbose --overwrite --ignore-time --transfer-all ${EXCLUDE_FOLDERS} - quit" 2>&1 | grep -v -i "operation not supported" - -# TODO: check return code - - # Remove any old core files no longer required - for FILE_TO_DELETE in "${OLD_FILES_TO_REMOVE[@]}"; do - remove_remote_file "${FILE_TO_DELETE}" "check" - done - } >> "$DISPLAY_MSG_LOG" 2>&1 + local NL="$( echo -e "\n " )" # Need space otherwise it doesn't work - not sure why + local CMDS=" lcd '${ALLSKY_WEBSITE}'" + CMDS+="${NL}set dns:fatal-timeout 10; set net:max-retries 2; set net:timeout 10" + # shellcheck disable=SC2086 + if [[ -n "${REMOTE_DIR}" ]]; then + CMDS+="${NL}cd '${REMOTE_DIR}'" + else + CMDS+="${NL}cd ." # for debugging + fi + CMDS+="${NL}mirror --reverse --no-perms --verbose --overwrite --ignore-time --transfer-all" + [[ -n ${EXCLUDE_FOLDERS} ]] && CMDS+=" ${EXCLUDE_FOLDERS}" + CMDS+="${NL}bye" + + local TMP="${ALLSKY_TMP}/remote_upload.txt" + echo -e "CMDS=${CMDS}\n======" > "${TMP}" + # shellcheck disable=SC2086 + lftp -u "${REMOTE_USER},${REMOTE_PASSWORD}" \ + ${REMOTE_PORT} "${REMOTE_PROTOCOL}://${REMOTE_HOST}" -e "${CMDS}" >> "${TMP}" 2>&1 + local RET_CODE=$? + + # Ignore stuff not supported by all FTP servers and stuff we don't want to see. + local IGNORE="operation not supported|command not understood|hostname checking disabled|Overwriting old file" + MSG="$( grep -v -i -E "${IGNORE}" "${TMP}" )" + # If the "mirror" command causes any of the messages above, + # they are counted as errors. + if [[ ${RET_CODE} -ne 0 ]]; then + MSG="$( echo -e "RET_CODE=${RET_CODE}\nCMDS=${CMDS}\n${MSG}" | sed -e 's/$/\\n/' )" + display_aborted "while uploading Website" "${MSG}" + fi + + display_msg --logonly info "$( indent --spaces "${MSG}" )" + + # Remove any old core files no longer required + for FILE_TO_DELETE in "${OLD_FILES_TO_REMOVE[@]}"; do + remove_remote_file "${FILE_TO_DELETE}" "check" + done display_msg --logonly info "Website upload complete" } @@ -592,21 +729,19 @@ function upload_remote_website() function upload_config_file() { local MSG="\nUploading remote Allsky configuration file" - display_info_box "${DIALOG_BACK_TITLE}" "${DIALOG_INSTALL}" "${MSG}" + display_box "--infobox" "${DIALOG_INSTALL}" "${MSG}" display_msg --logonly info "Uploading Website configuration file." - local REMOTE_DIR="$( settings ".remotewebsiteimagedir" "${SETTINGS_FILE}" )" - local RESULT="$( "${ALLSKY_SCRIPTS}/upload.sh" --remote-web \ + local ERR="$( "${ALLSKY_SCRIPTS}/upload.sh" --remote-web \ "${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE}" "${REMOTE_DIR}" \ - "${ALLSKY_WEBSITE_CONFIGURATION_NAME}" 2>&1 - )" + "${ALLSKY_WEBSITE_CONFIGURATION_NAME}" 2>&1 )" if [[ $? -eq 0 ]]; then MSG="${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE} uploaded to" MSG+="${REMOTE_DIR}/${ALLSKY_WEBSITE_CONFIGURATION_NAME}" show_debug_message "${MSG}" else - display_msg --logonly info " Failed: ${RESULT}" - display_aborted "at the configuration file upload" "true" + display_msg --logonly info " Failed: ${ERR}" + display_aborted "at the configuration file upload" "${ERR}" fi } @@ -629,7 +764,8 @@ usage_and_exit() echo echo "'--debug' adds addtional debugging information to the installation log." echo - echo "'--skipupload' Skips uploading of the remote Website code. Must only be used if advised by Allsky support." + echo "'--skipupload' Skips uploading of the remote Website code." + echo " Must only be used if advised by Allsky support." echo echo "'--auto' Accepts all prompts by default" echo @@ -639,10 +775,15 @@ usage_and_exit() exit "${RET}" } +# Disable the remote Website. +function disable_remote_website() +{ + update_json_file ".useremotewebsite" "false" "${SETTINGS_FILE}" + display_msg --logonly info "Remote Website temporarily disabled." +} # Enable the remote Website. function enable_remote_website() { - display_info_box "${DIALOG_BACK_TITLE}" "${DIALOG_INSTALL}" "\nEnabling remote Website" update_json_file ".useremotewebsite" "true" "${SETTINGS_FILE}" display_msg --logonly info "Remote Website enabled." } @@ -685,11 +826,12 @@ done [[ ${HELP} == "true" ]] && usage_and_exit 0 [[ ${OK} == "false" ]] && usage_and_exit 1 -display_msg --logonly info "STARTING INSTALLATION AT $( date ).\n" +display_msg --logonly info "STARTING INSTALLATION.\n" pre_install_checks display_welcome create_website_config +disable_remote_website upload_remote_website upload_config_file enable_remote_website diff --git a/scripts/functions.sh b/scripts/functions.sh index f4c860328..e2f42abf6 100644 --- a/scripts/functions.sh +++ b/scripts/functions.sh @@ -37,11 +37,11 @@ else fi ##### Start and Stop Allsky -start_Allsky() +function start_Allsky() { sudo systemctl start allsky 2> /dev/null } -stop_Allsky() +function stop_Allsky() { sudo systemctl stop allsky 2> /dev/null } @@ -1260,7 +1260,8 @@ function indent() # Python virtual environment PYTHON_VENV_ACTIVATED="false" -activate_python_venv() { +function activate_python_venv() +{ # TODO: will need to change when the OS after bookworm is released # If our next release is out, it won't support buster so may be check != bullseye ? @@ -1274,7 +1275,8 @@ activate_python_venv() { return 1 } -deactivate_python_venv() { +function deactivate_python_venv() +{ [[ ${PYTHON_VENV_ACTIVATED} == "true" ]] && deactivate } diff --git a/scripts/installUpgradeFunctions.sh b/scripts/installUpgradeFunctions.sh index d55029d0a..66bee794c 100644 --- a/scripts/installUpgradeFunctions.sh +++ b/scripts/installUpgradeFunctions.sh @@ -630,27 +630,35 @@ function prepare_local_website() # Update a Website configuration file from old to current version. function update_old_website_config_file() { - local FILE PRIOR_VERSION CURRENT_VERSION LOCAL_OR_REMOTE + local FILE PRIOR_VERSION CURRENT_VERSION FILE="${1}" PRIOR_VERSION="${2}" CURRENT_VERSION="${3}" - LOCAL_OR_REMOTE="${4}" # Current version: 2 if [[ ${PRIOR_VERSION} -eq 1 ]]; then - # Version 2 removed AllskyWebsiteVersion. + # Deletions: update_json_file -d ".AllskyWebsiteVersion" "" "${FILE}" + update_json_file -d ".homePage.onPi" "" "${FILE}" + update_array_field "${FILE}" "homePage.popoutIcons" "variable" "AllskyWebsiteVersion" "--delete" + + # Additions: + # Add in same place as new file + local NEW=' \"thumbnailsizex\": 100,\ + \"thumbnailsizey\": 75,\ + \"thumbnailsortorder\": \"ascending\",' + sed -i "/\"leftSidebar\"/i\ ${NEW}" "${FILE}" + + # Changes: + for i in "videos" "keograms" "startrails"; do + update_array_field "${FILE}" "homePage.leftSidebar" "url" "${i}" "${i}/" + done fi - # Set to current version. + # Set to current config and Allsky versions. update_json_file ".${WEBSITE_CONFIG_VERSION}" "${CURRENT_VERSION}" "${FILE}" - - if [[ ${LOCAL_OR_REMOTE} == "local" ]]; then - # Since we're installing a new Allsky, update the Allsky version. - # For remote Websites it'll be updated when the user updates the Website. - update_json_file ".${WEBSITE_ALLSKY_VERSION}" "${ALLSKY_VERSION}" "${FILE}" - fi + update_json_file ".${WEBSITE_ALLSKY_VERSION}" "${ALLSKY_VERSION}" "${FILE}" } ####