From 3fee42e9ada6581d97eb1652cb7739a7938e6e4c Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Sun, 6 Apr 2025 23:23:20 -0400 Subject: [PATCH 01/15] Update MerlinAU.sh --- MerlinAU.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index 0db270b3..697cc167 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -12,7 +12,7 @@ set -u readonly SCRIPT_VERSION=1.4.0 readonly SCRIPT_NAME="MerlinAU" ## Set to "master" for Production Releases ## -SCRIPT_BRANCH="master" +SCRIPT_BRANCH="dev" ##----------------------------------------## ## Modified by Martinski W. [2024-Jul-03] ## From 58279fa96c7845fa006c6a2b789ebba2f48db49e Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Mon, 7 Apr 2025 08:55:35 -0400 Subject: [PATCH 02/15] Bug Fixes for Fresh Installs Bug Fixes for Fresh Installs --- MerlinAU.sh | 69 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index 697cc167..253df58f 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -4,12 +4,12 @@ # # Original Creation Date: 2023-Oct-01 by @ExtremeFiretop. # Official Co-Author: @Martinski W. - Date: 2023-Nov-01 -# Last Modified: 2025-Mar-30 +# Last Modified: 2025-Apr-07 ################################################################### set -u ## Set version for each Production Release ## -readonly SCRIPT_VERSION=1.4.0 +readonly SCRIPT_VERSION=1.4.1 readonly SCRIPT_NAME="MerlinAU" ## Set to "master" for Production Releases ## SCRIPT_BRANCH="dev" @@ -2151,14 +2151,39 @@ _Mount_WebUI_() return 0 } -##-------------------------------------## -## Added by Martinski W. [2025-Feb-12] ## -##-------------------------------------## +##------------------------------------------## +## Modified by ExtremeFiretop [2025-Apr-07] ## +##------------------------------------------## _CheckFor_WebGUI_Page_() { - if "$mountWebGUI_OK" && \ - [ "$(_Check_WebGUI_Page_Exists_)" = "NONE" ] - then _Mount_WebUI_ ; fi + if "$mountWebGUI_OK" && \ + [ "$(_Check_WebGUI_Page_Exists_)" = "NONE" ] + then + updatedWebUIPage=false + # Only try to download if the local .asp file does NOT exist: + if [ ! -f "$SCRIPT_WEB_ASP_FILE" ] + then + if _CurlFileDownload_ "$SCRIPT_WEB_ASP_FILE" "$SCRIPT_WEB_ASP_PATH" + then + chmod 664 "$SCRIPT_WEB_ASP_PATH" + if "$updatedWebUIPage" + then + theWebPage="$(_GetWebUIPage_ "$SCRIPT_WEB_ASP_PATH")" + if [ -n "$theWebPage" ] && [ "$theWebPage" != "NONE" ] + then + sed -i "/url: \"$theWebPage\", tabName: \"$SCRIPT_NAME\"/d" "$TEMP_MENU_TREE" + rm -f "${SHARED_WEB_DIR}/$theWebPage" + rm -f "${SHARED_WEB_DIR}/$(echo "$theWebPage" | cut -f1 -d'.').title" + fi + _Mount_WebUI_ + fi + else + Say "${REDct}**ERROR**${NOct}: Unable to download latest WebUI ASP file for $SCRIPT_NAME." + fi + else + _Mount_WebUI_ + fi + fi } ##----------------------------------------## @@ -9587,13 +9612,12 @@ then _ReleaseLock_ ; exit 0 fi -##---------------------------------------## -## Added by ExtremeFiretop [2025-Feb-08] ## -##---------------------------------------## +##------------------------------------------## +## Modified by ExtremeFiretop [2025-Apr-07] ## +##------------------------------------------## _CheckAndSetBackupOption_() { - local currentBackupOption - currentBackupOption="$(Get_Custom_Setting "FW_Auto_Backupmon")" + local currentBackupOption="$(Get_Custom_Setting "FW_Auto_Backupmon")" if [ -f "/jffs/scripts/backupmon.sh" ] then # If setting is empty, add it to the configuration file # @@ -9661,15 +9685,16 @@ _EnableFWAutoUpdateChecks_() fi } -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-12] ## -##----------------------------------------## +##------------------------------------------## +## Modified by ExtremeFiretop [2025-Apr-07] ## +##------------------------------------------## _ConfirmCronJobForFWAutoUpdates_() { if [ $# -gt 0 ] && [ -n "$1" ] && \ echo "$1" | grep -qE "^(install|startup)$" then return 1 ; fi + FW_UpdateCronJobSchedule="$(Get_Custom_Setting FW_New_Update_Cron_Job_Schedule)" # Check if the PREVIOUS Cron Job ID already exists # if eval $cronListCmd | grep -qE "$CRON_JOB_RUN #${CRON_JOB_TAG_OLD}#$" then #If it exists, delete the OLD one & create a NEW one# @@ -10683,9 +10708,9 @@ _MainMenu_() done } -##-------------------------------------## -## Added by Martinski W. [2025-Jan-15] ## -##-------------------------------------## +##------------------------------------------## +## Modified by ExtremeFiretop [2025-Apr-07] ## +##------------------------------------------## _DoInitializationStartup_() { if ! _CheckForMinimumRequirements_ @@ -10694,6 +10719,9 @@ _DoInitializationStartup_() _DoExit_ 1 fi + _CheckAndSetBackupOption_ + _SetDefaultBuildType_ + if [ $# -gt 0 ] && [ -n "$1" ] && \ echo "$1" | grep -qE "^(install|startup)$" then return 1 ; fi @@ -10709,9 +10737,6 @@ _DoInitializationStartup_() _AutoStartupHook_ create 2>/dev/null _AutoServiceEvent_ create 2>/dev/null fi - - _CheckAndSetBackupOption_ - _SetDefaultBuildType_ } FW_InstalledVersion="$(_GetCurrentFWInstalledLongVersion_)" From 75c44160b32dbd2a4527b7d385d433ce9522835c Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Mon, 7 Apr 2025 09:11:49 -0400 Subject: [PATCH 03/15] Update MerlinAU.asp --- MerlinAU.asp | 13321 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 10639 insertions(+), 2682 deletions(-) diff --git a/MerlinAU.asp b/MerlinAU.asp index 3e21edf1..0127599b 100644 --- a/MerlinAU.asp +++ b/MerlinAU.asp @@ -1,2947 +1,10904 @@ - - - - - - - - - - - - -MerlinAU add-on for ASUSWRT-Merlin Firmware - - - - - - - - - - - - - - - -
- - - -
- - - - - - - -" /> -" /> - -" /> - -" /> -" /> -" /> -" /> -" /> -" /> - - - - - - - - -
  - - - - - - - -
- - - -
-
 
-
MerlinAU
-
-
This is the MerlinAU add-on integrated into the router WebUI -[ - Wiki ] - -
-
 
- - - - - - - - -
- - - - - - - - - - - -
Firmware Status (click to expand/collapse)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
F/W Product/Model ID:
F/W Variant Detected:Unknown
F/W Version Installed: - <% nvram_get("firmver"); %>.<% nvram_get("buildno"); %>.<% nvram_get("extendno"); %> -
F/W Update Available:NONE FOUND
Estimated Update Time:TBD
Last Notification Date:TBD
Changelog Approval:Disabled
- - - - - - - - - - - -
Settings Status (click to expand/collapse)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
F/W Update Check:Disabled
Changelog Check:Disabled
Beta-to-Release Updates:Disabled
Tailscale VPN Access:Disabled
Automatic Backups:Disabled
Auto-Updates for MerlinAU:Disabled
Email Notifications:Disabled
- -
 
- - - - - - -
Actions (click to expand/collapse)
-
- -- - - - - - - -
- -
- -
-
- -
- -
-
- -
- -
-
- -
 
- - - - - - - - - - -
Configuration (click to expand/collapse)
- - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- -
-
-
- -
-
-
-
- -
-
- - -
- - - -
- - - -
- - -
- Days: - - - - -
- - - - - - - -
-
-
- Hour: - -
-
- Minutes: - -
-
- - - -
- - - -
- -
- -
- -
- - - - -
- - - - -
- - - - -
- -
- -
-
- -
-
-
MerlinAU
-
- - - +FW_InstalledVersion="$(_GetCurrentFWInstalledLongVersion_)" +FW_InstalledVerStr="${GRNct}${FW_InstalledVersion}${NOct}" +FW_NewUpdateVerInit=TBD + +##----------------------------------------## +## Modified by Martinski W. [2025-Feb-12] ## +##----------------------------------------## +if [ $# -eq 0 ] || [ -z "$1" ] || \ + { [ $# -gt 1 ] && [ "$1" = "reload" ] ; } +then + if ! _AcquireLock_ cliMenuLock + then Say "Exiting..." ; exit 1 ; fi + + inMenuMode=true + _DoInitializationStartup_ + if _AcquireLock_ cliFileLock + then + _CheckForNewScriptUpdates_ + _ReleaseLock_ cliFileLock + fi + if [ "$ScriptAutoUpdateSetting" = "ENABLED" ] + then _AddScriptAutoUpdateCronJob_ ; fi + _ConfirmCronJobForFWAutoUpdates_ + _CheckFor_WebGUI_Page_ + + _MainMenu_ "$@" + _DoExit_ 0 +fi + +##----------------------------------------## +## Modified by Martinski W. [2025-Feb-15] ## +##----------------------------------------## +if [ $# -gt 0 ] +then + if ! _AcquireLock_ cliOptsLock + then Say "Exiting..." ; exit 1 ; fi + + inMenuMode=false + _DoInitializationStartup_ "$1" + _ConfirmCronJobForFWAutoUpdates_ "$1" + + case "$1" in + run_now) + if _AcquireLock_ cliFileLock + then + _RunFirmwareUpdateNow_ + _ReleaseLock_ cliFileLock + fi + ;; + processNodes) _ProcessMeshNodes_ 0 + ;; + addCronJob) _AddFWAutoUpdateCronJob_ + ;; + scriptAUCronJob) _AddScriptAutoUpdateCronJob_ + ;; + postRebootRun) _PostRebootRunNow_ + ;; + postUpdateEmail) _PostUpdateEmailNotification_ + ;; + about) _ShowAbout_ + ;; + help) _ShowHelp_ + ;; + checkupdates) + if _AcquireLock_ cliFileLock + then + _CheckForNewScriptUpdates_ + _ReleaseLock_ cliFileLock + fi + ;; + forceupdate) + if _AcquireLock_ cliFileLock + then + _SCRIPT_UPDATE_ force + _ReleaseLock_ cliFileLock + fi + ;; + develop) _ChangeToDev_ + ;; + stable) _ChangeToStable_ + ;; + startup) _DoStartupInit_ + ;; + install) _DoInstallation_ + ;; + uninstall) _DoUnInstallation_ + ;; + service_event) + if [ "$2" = "start" ] + then + case "$3" in + "${SCRIPT_NAME}uninstall" | \ + "${SCRIPT_NAME}uninstall_keepConfig") + if [ "$3" = "${SCRIPT_NAME}uninstall_keepConfig" ] + then keepConfigFile=true + else keepConfigFile=false + fi + _DoUnInstallation_ + sleep 1 + ;; + "${SCRIPT_NAME}downloadchangelog") + if "$isGNUtonFW" + then + _ManageChangelogGnuton_ "webuidownload" + else + _ManageChangelogMerlin_ "webuidownload" + fi + ;; + "${SCRIPT_NAME}approvechangelog") + currApprovalStatus="$(Get_Custom_Setting "FW_New_Update_Changelog_Approval")" + if [ "$currApprovalStatus" = "BLOCKED" ] + then + Update_Custom_Settings "FW_New_Update_Changelog_Approval" "APPROVED" + elif [ "$currApprovalStatus" = "APPROVED" ] + then + Update_Custom_Settings "FW_New_Update_Changelog_Approval" "BLOCKED" + fi + ;; + "${SCRIPT_NAME}blockchangelog") + currApprovalStatus="$(Get_Custom_Setting "FW_New_Update_Changelog_Approval")" + if [ "$currApprovalStatus" = "APPROVED" ] + then + Update_Custom_Settings "FW_New_Update_Changelog_Approval" "BLOCKED" + elif [ "$currApprovalStatus" = "BLOCKED" ] + then + Update_Custom_Settings "FW_New_Update_Changelog_Approval" "APPROVED" + fi + ;; + "${SCRIPT_NAME}checkupdate" | \ + "${SCRIPT_NAME}checkupdate_bypassDays") + if _AcquireLock_ cliFileLock + then + if [ "$3" = "${SCRIPT_NAME}checkupdate_bypassDays" ] + then bypassPostponedDays=true + else bypassPostponedDays=false + fi + _RunFirmwareUpdateNow_ + _ReleaseLock_ cliFileLock + fi + ;; + "${SCRIPT_NAME}config" | \ + "${SCRIPT_NAME}config_runLoginTest") + if _AcquireLock_ cliFileLock + then + if [ "$3" = "${SCRIPT_NAME}config_runLoginTest" ] + then runLoginCredentialsTest=true + else runLoginCredentialsTest=false + fi + _UpdateConfigFromWebUISettings_ + _ConfirmCronJobForFWAutoUpdates_ + _ReleaseLock_ cliFileLock + fi + ;; + *) + printf "${REDct}INVALID Parameters [$*].${NOct}\n" + ;; + esac + fi + ;; + *) printf "${REDct}INVALID Parameter [$*].${NOct}\n" + ;; + esac + _DoExit_ 0 +fi + +#EOF# From 13257303961f992e8bac4317336e8a78a43b93e8 Mon Sep 17 00:00:00 2001 From: ExtremeFiretop Date: Mon, 7 Apr 2025 09:13:48 -0400 Subject: [PATCH 04/15] Revert "Update MerlinAU.asp" This reverts commit 75c44160b32dbd2a4527b7d385d433ce9522835c. --- MerlinAU.asp | 13325 ++++++++++--------------------------------------- 1 file changed, 2684 insertions(+), 10641 deletions(-) diff --git a/MerlinAU.asp b/MerlinAU.asp index 0127599b..3e21edf1 100644 --- a/MerlinAU.asp +++ b/MerlinAU.asp @@ -1,10904 +1,2947 @@ -#!/bin/sh -################################################################### -# MerlinAU.sh (MerlinAutoUpdate) -# -# Original Creation Date: 2023-Oct-01 by @ExtremeFiretop. -# Official Co-Author: @Martinski W. - Date: 2023-Nov-01 -# Last Modified: 2025-Apr-07 -################################################################### -set -u - -## Set version for each Production Release ## -readonly SCRIPT_VERSION=1.4.1 -readonly SCRIPT_NAME="MerlinAU" -## Set to "master" for Production Releases ## -SCRIPT_BRANCH="dev" - -##----------------------------------------## -## Modified by Martinski W. [2024-Jul-03] ## -##----------------------------------------## -# Script URL Info # -readonly SCRIPT_URL_BASE="https://raw.githubusercontent.com/ExtremeFiretop/MerlinAutoUpdate-Router" -SCRIPT_URL_REPO="${SCRIPT_URL_BASE}/$SCRIPT_BRANCH" - -# Firmware URL Info # -readonly FW_SFURL_BASE="https://sourceforge.net/projects/asuswrt-merlin/files" -readonly FW_SFURL_RELEASE_SUFFIX="Release" -readonly FW_GITURL_RELEASE="https://api.github.com/repos/gnuton/asuswrt-merlin.ng/releases/latest" - -##----------------------------------------## -## Modified by Martinski W. [2024-May-31] ## -##----------------------------------------## -# Changelog Info # -readonly CL_URL_NG="${FW_SFURL_BASE}/Documentation/Changelog-NG.txt/download" -readonly CL_URL_386="${FW_SFURL_BASE}/Documentation/Changelog-386.txt/download" -readonly CL_URL_3006="${FW_SFURL_BASE}/Documentation/Changelog-3006.txt/download" - -readonly high_risk_terms="factory default reset|features are disabled|break backward compatibility|must be manually|strongly recommended" - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-24] ## -##----------------------------------------## -# For new script version updates from source repository # -DLRepoVersion="" -DLRepoVersionNum="" -DLRepoBuildNum=0 -ScriptBuildNum=0 -ScriptVersionNum="" -scriptUpdateNotify=0 - -##------------------------------------------## -## Modified by ExtremeFiretop [2024-Oct-02] ## -##------------------------------------------## -# For minimum supported firmware version check # -MinFirmwareVerCheckFailed=false -MinSupportedFirmwareVers="3004.386.12.6" - -# For router model check # -routerModelCheckFailed=false -offlineUpdateTrigger=false - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-18] ## -##----------------------------------------## -readonly NOct="\e[0m" -readonly BOLDct="\e[1m" -readonly BLKct="\e[1;30m" -readonly REDct="\e[1;31m" -readonly GRNct="\e[1;32m" -readonly YLWct="\e[1;33m" -readonly BLUEct="\e[1;34m" -readonly MGNTct="\e[1;35m" #Magenta# -readonly CYANct="\e[1;36m" -readonly WHITEct="\e[1;37m" -readonly CRITct="\e[1;41m" -readonly InvREDct="\e[41m" -readonly InvGRNct="\e[42m" -readonly InvMGNct="\e[45m" -readonly InvBREDct="\e[30;101m" -readonly InvBGRNct="\e[30;102m" -readonly InvBYLWct="\e[30;103m" -readonly InvBMGNct="\e[30;105m" - -readonly ScriptFileName="${0##*/}" -readonly ScriptFNameTag="${ScriptFileName%%.*}" -readonly ScriptDirNameD="${ScriptFNameTag}.d" - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-15] ## -##----------------------------------------## -readonly ADDONS_PATH="/jffs/addons" -readonly SCRIPTS_PATH="/jffs/scripts" -readonly SETTINGS_DIR="${ADDONS_PATH}/$ScriptDirNameD" -readonly CONFIG_FILE="${SETTINGS_DIR}/custom_settings.txt" -readonly SCRIPT_VERPATH="${SETTINGS_DIR}/version.txt" -readonly HELPER_JSFILE="${SETTINGS_DIR}/CheckHelper.js" -readonly PSWD_CHECK_JS="${SETTINGS_DIR}/PswdCheckStatus.js" -readonly CHANGELOG_PATH="${SETTINGS_DIR}/changelog.txt" -readonly SHARED_SETTINGS_FILE="${ADDONS_PATH}/custom_settings.txt" -readonly SHARED_WEB_DIR="$(readlink -f /www/user)" -readonly SCRIPT_WEB_DIR="${SHARED_WEB_DIR}/$SCRIPT_NAME" -readonly SCRIPT_WEB_ASP_FILE="${SCRIPT_NAME}.asp" -readonly SCRIPT_WEB_ASP_PATH="$SETTINGS_DIR/$SCRIPT_WEB_ASP_FILE" -readonly TEMP_MENU_TREE="/tmp/menuTree.js" -readonly ORIG_MENU_TREE="/www/require/modules/menuTree.js" -readonly WEBUI_LOCKFD=386 -readonly WEBUI_LOCKFILE="/tmp/addonwebui.lock" -readonly TEMPFILE="/tmp/MerlinAU_settings_$$.txt" -readonly webPageFileRegExp="user([1-9]|[1-2][0-9])[.]asp" -readonly webPageLineTabExp="\{url: \"$webPageFileRegExp\", tabName: " -readonly webPageLineRegExp="${webPageLineTabExp}\"$SCRIPT_NAME\"\}," - -# Give FIRST priority to built-in binaries over any other # -export PATH="/bin:/usr/bin:/sbin:/usr/sbin:$PATH" - -##-------------------------------------## -## Added by Martinski W. [2024-Sep-15] ## -##-------------------------------------## -# For handling 3rd-party add-on cron jobs # -readonly USB_OPT_DIRPATH1="/opt" -readonly USB_OPT_DIRPATH2="/tmp/opt" -readonly USB_MNT_DIRPATH1="/mnt" -readonly USB_MNT_DIRPATH2="/tmp/mnt" - -readonly cronJobsRegEx1="[[:blank:]]+${ADDONS_PATH}/.* " -readonly cronJobsRegEx2="[[:blank:]]+${SCRIPTS_PATH}/.* " -readonly cronJobsRegEx3="[[:blank:]]+${USB_OPT_DIRPATH1}/.* " -readonly cronJobsRegEx4="[[:blank:]]+${USB_OPT_DIRPATH2}/.* " -readonly cronJobsRegEx5="[[:blank:]]+${USB_MNT_DIRPATH1}/.* " -readonly cronJobsRegEx6="[[:blank:]]+${USB_MNT_DIRPATH2}/.* " -readonly addonCronJobList="/home/root/addonCronJobList_$$.txt" - -##----------------------------------------## -## Modified by Martinski W. [2024-Jun-05] ## -##----------------------------------------## -ScriptsDirPath="$SCRIPTS_PATH" -ScriptFilePath="${SCRIPTS_PATH}/${SCRIPT_NAME}.sh" - -if [ ! -f "$ScriptFilePath" ] -then - ScriptsDirPath="$(pwd)" - ScriptFilePath="$(pwd)/$ScriptFileName" -fi - -##------------------------------------------## -## Modified by ExtremeFiretop [2024-Dec-21] ## -##------------------------------------------## -#-------------------------------------------------------# -# We'll use the built-in AMTM email configuration file -# to send email notifications *IF* enabled by the user. -#-------------------------------------------------------# -readonly FW_UpdateEMailFormatTypeDefault=HTML -readonly FW_UpdateEMailNotificationDefault=DISABLED -readonly amtmMailDirPath="/jffs/addons/amtm/mail" -readonly amtmMailConfFile="${amtmMailDirPath}/email.conf" -readonly amtmMailPswdFile="${amtmMailDirPath}/emailpw.enc" -readonly tempEMailContent="/tmp/var/tmp/tempEMailContent.$$.TXT" -readonly tempNodeEMailList="/tmp/var/tmp/tempNodeEMailList.$$.TXT" -readonly tempEMailBodyMsg="/tmp/var/tmp/tempEMailBodyMsg.$$.TXT" -readonly saveEMailInfoMsg="${SETTINGS_DIR}/savedEMailInfoMsg.SAVE.TXT" -readonly theEMailDateTimeFormat="%Y-%b-%d %a %I:%M:%S %p %Z" - -if [ -z "$(which crontab)" ] -then cronListCmd="cru l" -else cronListCmd="crontab -l" -fi - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-22] ## -##----------------------------------------## -inMenuMode=true -isInteractive=false -FlashStarted=false -MerlinChangeLogURL="" -GnutonChangeLogURL="" -keepConfigFile=false -bypassPostponedDays=false -runLoginCredentialsTest=false - -# Main LAN Network Info # -readonly myLAN_HostName="$(nvram get lan_hostname)" -readonly mainLAN_IFname="$(nvram get lan_ifname)" -readonly mainLAN_IPaddr="$(nvram get lan_ipaddr)" -readonly mainNET_IPaddr="$(ip route show | grep -E "[[:blank:]]+dev[[:blank:]]+${mainLAN_IFname}[[:blank:]]+proto[[:blank:]]+" | awk -F ' ' '{print $1}')" - -# RegExp for IPv4 address # -readonly IPv4octet_RegEx="([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" -readonly IPv4addrs_RegEx="(${IPv4octet_RegEx}\.){3}${IPv4octet_RegEx}" -readonly IPv4privt_RegEx="(^10\.|^172\.1[6-9]\.|^172\.2[0-9]\.|^172\.3[0-1]\.|^192\.168\.)" - -##----------------------------------------## -## Modified by Martinski W. [2024-Oct-03] ## -##----------------------------------------## -readonly fwInstalledBaseVers="$(nvram get firmver | sed 's/\.//g')" -readonly fwInstalledBuildVers="$(nvram get buildno)" -readonly fwInstalledExtendNum="$(nvram get extendno)" -readonly fwInstalledInnerVers="$(nvram get innerver)" -readonly fwInstalledBranchVer="${fwInstalledBaseVers}.$(echo "$fwInstalledBuildVers" | awk -F'.' '{print $1}')" - -##-------------------------------------## -## Added by Martinski W. [2024-Oct-03] ## -##-------------------------------------## -readonly MinSupportedFW_3004_386_Ver="3004.386.12.6" -readonly MinSupportedFW_3004_388_Ver="3004.388.6.2" -readonly MinSupportedFW_3006_102_Ver="3004.388.8.0" - -case "$fwInstalledBranchVer" in - "3004.386") MinSupportedFirmwareVers="$MinSupportedFW_3004_386_Ver" ;; - "3004.388") MinSupportedFirmwareVers="$MinSupportedFW_3004_388_Ver" ;; - "3006.102") MinSupportedFirmwareVers="$MinSupportedFW_3006_102_Ver" ;; -esac - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-19] ## -##----------------------------------------## -aiMeshNodes_OK=false -mountWebGUI_OK=false -inMainRouterMode=false -inAccessPointMode=false - -readonly nvramSWmode="$(nvram get sw_mode)" -if [ "$nvramSWmode" = "1" ] -then - mountWebGUI_OK=true - aiMeshNodes_OK=true - inMainRouterMode=true -else - if [ "$nvramSWmode" = "3" ] && \ - [ "$(nvram get wlc_psta)" = "0" ] - then - mountWebGUI_OK=true - aiMeshNodes_OK=false - inAccessPointMode=true - fi -fi - -readonly mainMenuReturnPromptStr="Press to return to the Main Menu..." -readonly advnMenuReturnPromptStr="Press to return to the Advanced Options Menu..." -readonly logsMenuReturnPromptStr="Press to return to the Log Options Menu..." -theMenuReturnPromptMsg="$mainMenuReturnPromptStr" -readonly SEPstr="----------------------------------------------------------" - -##-------------------------------------## -## Added by Martinski W. [2024-Nov-24] ## -##-------------------------------------## -# menu setup variables # -readonly padStr=" " -readonly theExitStr="${GRNct}e${NOct}=Exit to Main Menu" -readonly theMUExitStr="${GRNct}e${NOct}=Exit" -readonly theADExitStr="${GRNct}e${NOct}=Exit to Advanced Options Menu" -readonly theLGExitStr="${GRNct}e${NOct}=Exit to Log Options Menu" -readonly menuCancelAndExitStr="${GRNct}e${NOct}=Exit Menu" -readonly menuSavedThenExitStr="${GRNct}s${NOct}=Save&Exit" -readonly menuReturnToBeginStr="${GRNct}b${NOct}=Back to Top" - -##-------------------------------------## -## Added by Martinski W. [2024-Aug-15] ## -##-------------------------------------## -routerLoginFailureMsg="Please try the following: -1. Confirm that you are *not* already logged into the router webGUI using a web browser. -2. Check that the \"Enable Access Restrictions\" option from the webGUI is *not* set up - to restrict access to the router webGUI from the router's IP address [${GRNct}${mainLAN_IPaddr}${NOct}]. -3. Confirm your password via the \"Set Router Login Password\" option from the Main Menu." - -[ -t 0 ] && ! tty | grep -qwi "NOT" && isInteractive=true - -##----------------------------------------## -## Modified by Martinski W. [2023-Dec-23] ## -##----------------------------------------## -userLOGFile="" -userTraceFile="${SETTINGS_DIR}/${ScriptFNameTag}_Trace.LOG" -userDebugFile="${SETTINGS_DIR}/${ScriptFNameTag}_Debug.LOG" -LOGdateFormat="%Y-%m-%d %H:%M:%S" -_LogMsgNoTime_() { _UserLogMsg_ "_NOTIME_" "$@" ; } - -_UserTraceLog_() -{ - local logTime="$(date +"$LOGdateFormat")" - if [ $# -eq 0 ] || [ -z "$1" ] - then - echo >> "$userTraceFile" - elif [ $# -eq 1 ] - then - echo "$logTime" "$1" >> "$userTraceFile" - elif [ "$1" = "_NOTIME_" ] - then - echo "$2" >> "$userTraceFile" - else - echo "$logTime" "${1}: $2" >> "$userTraceFile" - fi -} - -_UserLogMsg_() -{ - if [ -z "$userLOGFile" ] || [ ! -f "$userLOGFile" ] - then return 1 ; fi - - local logTime="$(date +"$LOGdateFormat")" - if [ $# -eq 0 ] || [ -z "$1" ] - then - echo >> "$userLOGFile" - elif [ $# -eq 1 ] - then - echo "$logTime" "$1" >> "$userLOGFile" - elif [ "$1" = "_NOTIME_" ] - then - echo "$2" >> "$userLOGFile" - else - echo "$logTime" "${1}: $2" >> "$userLOGFile" - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-15] ## -##----------------------------------------## -Say() -{ - local logMsg - "$isInteractive" && printf "${1}\n" - # Remove all "color escape sequences" from the system log file entries # - logMsg="$(echo "$1" | sed 's/\\\e\[[0-1]m//g ; s/\\\e\[[0-1];[3-4][0-9]m//g')" - _UserLogMsg_ "$logMsg" - printf "$logMsg" | logger -t "[${SCRIPT_NAME}] $$" -} - -##----------------------------------------------## -## Added/Modified by Martinski W. [2023-Nov-20] ## -##----------------------------------------------## -_WaitForEnterKey_() -{ - ! "$isInteractive" && return 0 - local promptStr - - if [ $# -gt 0 ] && [ -n "$1" ] - then promptStr="$1" - else promptStr="Press to continue..." - fi - - printf "\n$promptStr" - read -rs EnterKEY ; echo -} - -##-------------------------------------## -## Modified Martinski W. [2025-Feb-18] ## -##-------------------------------------## -_WaitForYESorNO_() -{ - local defltCode=0 defltAnswer=NO promptStr - - if [ $# -eq 0 ] - then defltCode=0 ; defltAnswer=NO - elif [ "$1" = "NO" ] - then defltCode=1 ; defltAnswer=NO - elif [ "$1" = "YES" ] - then defltCode=0 ; defltAnswer=YES - fi - - ! "$isInteractive" && return "$defltCode" - - if [ $# -eq 0 ] || [ -z "$1" ] || \ - echo "$1" | grep -qE "^(YES|NO)$" - then promptStr=" [yY|nN]? " - else promptStr="$1 [yY|nN]? " - fi - - printf "$promptStr" ; read -r YESorNO - [ -z "$YESorNO" ] && YESorNO="$defltAnswer" - if echo "$YESorNO" | grep -qE "^([Yy](es)?|YES)$" - then echo "OK" ; return 0 - else echo "NO" ; return 1 - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-11] ## -##----------------------------------------## -readonly LockFilePath="/tmp/var/${ScriptFNameTag}.LOCK" -readonly LockTypeRegEx="(cliMenuLock|cliOptsLock|cliFileLock)" - -_FindLockFileTypes_() -{ grep -woE "$LockTypeRegEx" "$LockFilePath" | tr '\n' ' ' | sed 's/[ ]*$//' ; } - -_ReleaseLock_() -{ - local lockType - if [ $# -eq 0 ] || [ -z "$1" ] - then lockType="" - else lockType="$1" - fi - if [ -s "$LockFilePath" ] && \ - [ "$(wc -l < "$LockFilePath")" -gt 1 ] - then - if [ -z "$lockType" ] - then sed -i "/^$$|/d" "$LockFilePath" - else sed -i "/.*|${1}$/d" "$LockFilePath" - fi - [ -s "$LockFilePath" ] && return 0 - fi - rm -f "$LockFilePath" -} - -## Defaults ## -LockMaxTimeoutSecs=120 -LockFileMaxAgeSecs=600 #10-minutes# - -if [ $# -eq 0 ] || [ -z "$1" ] -then - #Interactive Mode# - LockMaxTimeoutSecs=3 - LockFileMaxAgeSecs=1200 -else - case "$1" in - run_now|resetLockFile) - LockMaxTimeoutSecs=3 - LockFileMaxAgeSecs=1200 - ;; - startup|addCronJob) - LockMaxTimeoutSecs=600 - LockFileMaxAgeSecs=900 - ;; - esac -fi - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-15] ## -##----------------------------------------## -_AcquireLock_() -{ - local retCode waitTimeoutSecs - local lockFileSecs ageOfLockSecs oldPID - local lockTypeReq lockTypeFound - - if [ $# -gt 0 ] && [ -n "$1" ] - then lockTypeReq="$1" - else lockTypeReq="cliAnyLock" - fi - - _CreateLockFile_() - { echo "$$|$lockTypeReq" > "$LockFilePath" ; } - - if [ ! -f "$LockFilePath" ] - then _CreateLockFile_ ; return 0 - fi - - retCode=1 - lockTypeFound="" - waitTimeoutSecs=0 - - while true - do - if [ -s "$LockFilePath" ] - then - oldPID="$(head -n1 "$LockFilePath" | awk -F '|' '{print $1}')" - if [ -n "$oldPID" ] && ! pidof "$ScriptFileName" | grep -qow "$oldPID" - then sed -i "/^${oldPID}|/d" "$LockFilePath" - fi - lockFileSecs="$(date +%s -r "$LockFilePath")" - lockTypeFound="$(_FindLockFileTypes_)" - if [ "$lockTypeReq" != "cliAnyLock" ] && \ - ! echo "$lockTypeFound" | grep -qw "$lockTypeReq" - then # Specific "Lock Type" NOT found # - echo "$$|$lockTypeReq" >> "$LockFilePath" - retCode=0 ; break - fi - [ -z "$lockTypeFound" ] && lockTypeFound="noTypeLock" - else - _CreateLockFile_ - retCode=0 ; break - fi - - ageOfLockSecs="$(($(date +%s) - lockFileSecs))" - if [ "$ageOfLockSecs" -gt "$LockFileMaxAgeSecs" ] - then - Say "Stale Lock Found (older than $LockFileMaxAgeSecs secs). Resetting lock file..." - if [ -n "$oldPID" ] && \ - pidof "$ScriptFileName" | grep -qow "$oldPID" && \ - kill -EXIT "$oldPID" 2>/dev/null - then - kill -TERM "$oldPID" ; wait "$oldPID" - fi - _CreateLockFile_ - retCode=0 ; break - elif [ "$waitTimeoutSecs" -le "$LockMaxTimeoutSecs" ] - then - if [ "$((waitTimeoutSecs % 10))" -eq 0 ] - then - Say "Lock Found [$lockTypeFound: $ageOfLockSecs secs]. Waiting for script [PID=$oldPID] to exit [Timer: $waitTimeoutSecs secs]" - fi - sleep 5 - waitTimeoutSecs="$((waitTimeoutSecs + 5))" - else - Say "${REDct}**ERROR**${NOct}: The shell script ${ScriptFileName} [PID=$oldPID] is already running [$lockTypeFound: $ageOfLockSecs secs]" - retCode=1 ; break - fi - done - return "$retCode" -} - -##-------------------------------------## -## Added by Martinski W. [2023-Dec-26] ## -##-------------------------------------## -_DoExit_() -{ - local exitCode=0 - [ $# -gt 0 ] && [ -n "$1" ] && exitCode="$1" - _ReleaseLock_ ; exit "$exitCode" -} - -##------------------------------------------## -## Modified by ExtremeFiretop [2024-May-21] ## -##------------------------------------------## -_ShowLogo_() -{ - echo -e "${YLWct}" - echo -e " __ __ _ _ _ _ " - echo -e " | \/ | | (_) /\ | | | |" - echo -e " | \ / | ___ _ __| |_ _ __ / \ | | | |" - echo -e " | |\/| |/ _ | '__| | | '_ \ / /\ \| | | |" - echo -e " | | | | __| | | | | | | |/ ____ | |__| |" - echo -e " |_| |_|\___|_| |_|_|_| |_/_/ \_\____/ ${GRNct}v${SCRIPT_VERSION}" - echo -e "${NOct}" -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-19] ## -##----------------------------------------## -_ShowAbout_() -{ - local webUI_Page webUI_URL="[Not Available]" - if "$mountWebGUI_OK" - then - webUI_Page="$(_Check_WebGUI_Page_Exists_)" - if [ "$webUI_Page" != "NONE" ] - then webUI_URL="$(_GetRouterURL_)/$webUI_Page" - fi - fi - - clear - _ShowLogo_ - cat < /dev/null 2>&1 - sleep "$blinkRateSecs" - done - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-May-31] ## -##----------------------------------------## -_Reset_LEDs_() -{ - local doTrace=false - [ $# -gt 0 ] && [ "$1" -eq 1 ] && doTrace=false - if "$doTrace" - then - Say "START _Reset_LEDs_" - _UserTraceLog_ "START _Reset_LEDs_" - fi - - # Check if the process with that PID is still running # - if [ -n "$Toggle_LEDs_PID" ] && \ - kill -EXIT "$Toggle_LEDs_PID" 2>/dev/null - then - kill -TERM "$Toggle_LEDs_PID" - wait "$Toggle_LEDs_PID" - # Set LEDs to their "initial state" # - nvram set ${nvramLEDsVar}="$LEDsInitState" - /sbin/service restart_leds >/dev/null 2>&1 - sleep 2 - fi - Toggle_LEDs_PID="" - - if "$doTrace" - then - Say "EXIT _Reset_LEDs_" - _UserTraceLog_ "EXIT _Reset_LEDs_" - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Apr-06] ## -##----------------------------------------## -_GetRouterURL_() -{ - local urlProto urlDomain urlPort - - if [ "$(nvram get http_enable)" = "1" ] - then urlProto="https" - else urlProto="http" - fi - - urlDomain="$(nvram get lan_domain)" - if [ -z "$urlDomain" ] - then urlDomain="$mainLAN_IPaddr" - else urlDomain="${myLAN_HostName}.$urlDomain" - fi - - urlPort="$(nvram get "${urlProto}_lanport")" - if [ "$urlPort" -eq 80 ] || [ "$urlPort" -eq 443 ] - then urlPort="" - else urlPort=":$urlPort" - fi - - echo "${urlProto}://${urlDomain}${urlPort}" -} - -##----------------------------------------------## -## Added/Modified by Martinski W. [2023-Nov-20] ## -##----------------------------------------------## -_GetRouterModelID_() -{ - local retCode=1 routerModelID="" - local nvramModelKeys="odmpid wps_modelnum model build_name" - for nvramKey in $nvramModelKeys - do - routerModelID="$(nvram get "$nvramKey")" - [ -n "$routerModelID" ] && retCode=0 && break - done - echo "$routerModelID" ; return "$retCode" -} - -##----------------------------------------------## -## Added/Modified by Martinski W. [2023-Nov-20] ## -##----------------------------------------------## -_GetRouterProductID_() -{ - local retCode=1 routerProductID="" - local nvramProductKeys="productid build_name odmpid" - for nvramKey in $nvramProductKeys - do - routerProductID="$(nvram get "$nvramKey")" - [ -n "$routerProductID" ] && retCode=0 && break - done - echo "$routerProductID" ; return "$retCode" -} - -##-------------------------------------## -## Added by Martinski W. [2023-Nov-28] ## -##-------------------------------------## -_ScriptVersionStrToNum_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] ; then echo 0 ; return 1 ; fi - local verNum verStr - - verStr="$(echo "$1" | awk -F '_' '{print $1}')" - verNum="$(echo "$verStr" | awk -F '.' '{printf ("%d%03d%03d\n", $1,$2,$3);}')" - verNum="$(echo "$verNum" | sed 's/^0*//')" - echo "$verNum" ; return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Aug-11] ## -##----------------------------------------## -_GetFirmwareVariantFromRouter_() -{ - local hasGNUtonFW=false - - ##FOR TESTING/DEBUG ONLY## - if false # Change to true for forcing GNUton flag # - then hasGNUtonFW=true ; return 0 ; fi - ##FOR TESTING/DEBUG ONLY## - - # Check if installed F/W NVRAM vars contain "gnuton" # - if echo "$fwInstalledInnerVers" | grep -iq "gnuton" || \ - echo "$fwInstalledExtendNum" | grep -iq "gnuton" - then hasGNUtonFW=true ; fi - - echo "$hasGNUtonFW" ; return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-May-31] ## -##----------------------------------------## -_FWVersionStrToNum_() -{ - if [ $# -lt 2 ] || [ -z "$1" ] || [ -z "$2" ] - then echo ; return 1 ; fi - - USE_BETA_WEIGHT="$(Get_Custom_Setting FW_Allow_Beta_Production_Up)" - - local verNum verStr="$1" nonProductionVersionWeight=0 - local fwBasecodeVers="" numOfFields - - #-------------------------------------------------------------- - # Handle any 'alpha/beta' in the version string to be sure - # that we always get good numerical values for comparison. - #-------------------------------------------------------------- - if echo "$verStr" | grep -qiE '(alpha|beta)' - then - # Adjust weight value if "Beta-to-Production" update is enabled # - [ "$USE_BETA_WEIGHT" = "ENABLED" ] && nonProductionVersionWeight=-100 - - # Replace '.alpha|.beta' and anything following it with ".0" # - verStr="$(echo "$verStr" | sed 's/[.][Aa]lpha.*/.0/ ; s/[.][Bb]eta.*/.0/')" - # Remove 'alpha|beta' and anything following it # - verStr="$(echo "$verStr" | sed 's/[_-]\?[Aa]lpha.*// ; s/[_-]\?[Bb]eta.*//')" - fi - - numOfFields="$(echo "$verStr" | awk -F '.' '{print NF}')" - - if [ "$numOfFields" -lt "$2" ] - then fwBasecodeVers="$fwInstalledBaseVers" ; fi - - #----------------------------------------------------------- - # Temporarily remove Basecode version to avoid issues with - # integers greater than the maximum 32-bit signed integer - # when doing arithmetic computations with shell cmds. - #----------------------------------------------------------- - if [ "$numOfFields" -gt 3 ] - then - fwBasecodeVers="$(echo "$verStr" | cut -d'.' -f1)" - verStr="$(echo "$verStr" | cut -d'.' -f2-)" - fi - verNum="$(echo "$verStr" | awk -F '.' '{printf ("%d%02d%02d\n", $1,$2,$3);}')" - - # Subtract non-production weight from the version number # - verNum="$((verNum + nonProductionVersionWeight))" - - # Now prepend the F/W Basecode version # - [ -n "$fwBasecodeVers" ] && verNum="${fwBasecodeVers}$verNum" - - echo "$verNum" ; return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-19] ## -##----------------------------------------## -if "$inMainRouterMode" -then - readonly FW_Update_CRON_DefaultSchedule="0 0 * * *" -else - ## Set 20 minutes AFTER for APs and AiMesh Nodes ## - readonly FW_Update_CRON_DefaultSchedule="20 0 * * *" -fi - -## Recommended 15 minutes BEFORE the F/W Update ## -readonly ScriptAU_CRON_DefaultSchedule="45 23 * * *" - -## For Automatic Script Updates Cron Schedule ## -readonly SW_Update_CRON_DefaultSchedDays="* x *" - -readonly CRON_MINS_RegEx="([0-9]|[1-5][0-9])" -readonly CRON_HOUR_RegEx="([0-9]|1[0-9]|2[0-3])" - -readonly CRON_DAYofMONTH_rexp1="([1-9]|[1-2][0-9]|3[0-1])" -readonly CRON_DAYofMONTH_rexp2="${CRON_DAYofMONTH_rexp1}[-]${CRON_DAYofMONTH_rexp1}" -readonly CRON_DAYofMONTH_rexp3="${CRON_DAYofMONTH_rexp2}[/][2-9]" -readonly CRON_DAYofMONTH_rexp4="${CRON_DAYofMONTH_rexp1}([,]${CRON_DAYofMONTH_rexp1})+" -readonly CRON_DAYofMONTH_RegEx="($CRON_DAYofMONTH_rexp1|$CRON_DAYofMONTH_rexp2|$CRON_DAYofMONTH_rexp3|$CRON_DAYofMONTH_rexp4)" - -readonly CRON_DAYofWEEK_Names="([S|s]un|[M|m]on|[T|t]ue|[W|w]ed|[T|t]hu|[F|f]ri|[S|s]at)" -readonly CRON_DAYofWEEK_rexp1="[0-6][-][0-6][/][2-3]" -readonly CRON_DAYofWEEK_rexp2="${CRON_DAYofWEEK_Names}|[0-6]" -readonly CRON_DAYofWEEK_rexp3="${CRON_DAYofWEEK_Names}[-]${CRON_DAYofWEEK_Names}|[0-6][-][0-6]" -readonly CRON_DAYofWEEK_rexp4="${CRON_DAYofWEEK_Names}([,]${CRON_DAYofWEEK_Names})+|[0-6]([,][0-6])+" -readonly CRON_DAYofWEEK_RegEx="($CRON_DAYofWEEK_rexp1|$CRON_DAYofWEEK_rexp2|$CRON_DAYofWEEK_rexp3|$CRON_DAYofWEEK_rexp4)" - -readonly CRON_MONTH_NAMES="(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)" -readonly CRON_MONTH_RegEx="$CRON_MONTH_NAMES([\/,-]$CRON_MONTH_NAMES)*|([*1-9]|1[0-2])([\/,-]([1-9]|1[0-2]))*" - -readonly CRON_UNKNOWN_DATE="**ERROR**: UNKNOWN Date Found" - -##------------------------------------------## -## Modified by Martinski W. [2024-Aug-06] ## -##------------------------------------------## -# To postpone a firmware update for a few days # -readonly FW_UpdateMinimumPostponementDays=0 -readonly FW_UpdateDefaultPostponementDays=15 -readonly FW_UpdateMaximumPostponementDays=199 -readonly FW_UpdateNotificationDateFormat="%Y-%m-%d_%H:%M:00" - -readonly MODEL_ID="$(_GetRouterModelID_)" -readonly PRODUCT_ID="$(_GetRouterProductID_)" - -##FOR TESTING/DEBUG ONLY## -##readonly PRODUCT_ID="TUF-AX3000_V2" -##readonly MODEL_ID="$PRODUCT_ID" -##FOR TESTING/DEBUG ONLY## - -readonly FW_FileName="${PRODUCT_ID}_firmware" -readonly FW_SFURL_RELEASE="${FW_SFURL_BASE}/${PRODUCT_ID}/${FW_SFURL_RELEASE_SUFFIX}/" -readonly isGNUtonFW="$(_GetFirmwareVariantFromRouter_)" - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-05] ## -##----------------------------------------## -readonly FW_RouterProductID="${GRNct}${PRODUCT_ID}${NOct}" -# Some Model IDs have a lower case suffix of the same Product ID # -if [ "$PRODUCT_ID" = "$(echo "$MODEL_ID" | tr 'a-z' 'A-Z')" ] -then - readonly FW_RouterModelID="$PRODUCT_ID" - readonly FW_RouterModelIDstr="$FW_RouterProductID" -else - readonly FW_RouterModelID="${PRODUCT_ID}/$MODEL_ID" - readonly FW_RouterModelIDstr="${FW_RouterProductID}/${GRNct}${MODEL_ID}${NOct}" -fi - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-05] ## -##----------------------------------------## -_ChangeToDev_() -{ - if ! _AcquireLock_ cliFileLock - then return 1 - fi - SCRIPT_BRANCH="dev" - SCRIPT_URL_REPO="${SCRIPT_URL_BASE}/$SCRIPT_BRANCH" - _SCRIPT_UPDATE_ force - _DoExit_ 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-05] ## -##----------------------------------------## -_ChangeToStable_() -{ - if ! _AcquireLock_ cliFileLock - then return 1 - fi - SCRIPT_BRANCH="master" - SCRIPT_URL_REPO="${SCRIPT_URL_BASE}/$SCRIPT_BRANCH" - _SCRIPT_UPDATE_ force - _DoExit_ 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Nov-15] ## -##----------------------------------------## -#-------------------------------------------------------------# -# Since a list of current mount points can have a different -# order after each reboot, or when USB drives are unmounted -# (unplugged) & then mounted (plugged in) manually by users, -# to validate a given mount point path selection we have to -# go through the current list & check for the specific path. -# We also make a special case for Entware "/opt/" paths. -#-------------------------------------------------------------# -_ValidateUSBMountPoint_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi - - local mounPointPaths expectedPath mountPointList - local symblPath realPath1 realPath2 foundPathOK - local mountPointRegExp="^/dev/sd.* /tmp/mnt/.*" - - mounPointPaths="$(grep "$mountPointRegExp" /proc/mounts | awk -F ' ' '{print $2}')" - [ -z "$mounPointPaths" ] && return 1 - - expectedPath="$1" - if echo "$1" | grep -qE "^(/opt/|/tmp/opt/)" && [ -d /tmp/opt ] - then - realPath1="$(readlink -f /tmp/opt)" - realPath2="$(ls -l /tmp/opt | awk -F ' ' '{print $11}')" - symblPath="$(ls -l /tmp/opt | awk -F ' ' '{print $9}')" - [ -L "$symblPath" ] && [ -n "$realPath1" ] && \ - [ -n "$realPath2" ] && [ "$realPath1" = "$realPath2" ] && \ - expectedPath="$(/usr/bin/dirname "$realPath1")" - fi - - mountPointList="" - foundPathOK=false - - for thePATH in $mounPointPaths - do - if echo "${expectedPath}/" | grep -qE "^${thePATH}/" - then foundPathOK=true ; break ; fi - mountPointList="$mountPointList $thePATH" - done - "$foundPathOK" && return 0 - - ## Report found Mount Points on failure ## - if [ $# -gt 1 ] && [ "$2" -eq 1 ] && [ -n "$mountPointList" ] - then Say "Mount points found:\n$mountPointList" ; fi - return 1 -} - -##----------------------------------------## -## Modified by Martinski W. [2023-Nov-24] ## -##----------------------------------------## -if USBMountPoint="$(_GetDefaultUSBMountPoint_)" -then - USBConnected="${GRNct}True${NOct}" - readonly FW_Update_ZIP_DefaultSetupDIR="$USBMountPoint" - readonly FW_Update_LOG_BASE_DefaultDIR="$USBMountPoint" -else - USBConnected="${REDct}False${NOct}" - readonly FW_Update_ZIP_DefaultSetupDIR="/home/root" - readonly FW_Update_LOG_BASE_DefaultDIR="$ADDONS_PATH" -fi - -##-------------------------------------## -## Added by Martinski W. [2025-Jan-15] ## -##-------------------------------------## -_SetUp_FW_UpdateZIP_DirectoryPaths_() -{ - local theDirPath="" - if [ $# -eq 1 ] && [ -n "$1" ] && [ -d "$1" ] - then - theDirPath="$1" - else - theDirPath="$(Get_Custom_Setting FW_New_Update_ZIP_Directory_Path)" - fi - FW_ZIP_BASE_DIR="$theDirPath" - FW_ZIP_DIR="${FW_ZIP_BASE_DIR}/$FW_ZIP_SUBDIR" - FW_ZIP_FPATH="${FW_ZIP_DIR}/${FW_FileName}.zip" -} - -##-------------------------------------## -## Added by Martinski W. [2025-Jan-15] ## -##-------------------------------------## -_SetUp_FW_UpdateLOG_DirectoryPaths_() -{ - local theDirPath="" - if [ $# -eq 1 ] && [ -n "$1" ] && [ -d "$1" ] - then - theDirPath="$1" - else - theDirPath="$(Get_Custom_Setting FW_New_Update_LOG_Directory_Path)" - fi - FW_LOG_BASE_DIR="$theDirPath" - FW_LOG_DIR="${FW_LOG_BASE_DIR}/$FW_LOG_SUBDIR" -} - -##-------------------------------------## -## Added by Martinski W. [2025-Mar-07] ## -##-------------------------------------## -_WriteVarDefToPswdCheckJSFile_() -{ - if [ $# -lt 2 ] || [ -z "$1" ] || [ -z "$2" ] - then return 1; fi - - local varValue fixedVal - if [ $# -eq 3 ] && [ "$3" = "true" ] - then varValue="$2" - else varValue="'${2}'" - fi - - if [ ! -s "$PSWD_CHECK_JS" ] - then - echo "var $1 = ${varValue};" > "$PSWD_CHECK_JS" - elif ! grep -q "^var $1 =.*" "$PSWD_CHECK_JS" - then - echo "var $1 = ${varValue};" >> "$PSWD_CHECK_JS" - elif ! grep -q "^var $1 = ${varValue};" "$PSWD_CHECK_JS" - then - fixedVal="$(echo "$varValue" | sed 's/[\/&]/\\&/g')" - sed -i "s/^var $1 =.*/var $1 = ${fixedVal};/" "$PSWD_CHECK_JS" - fi -} - -##-------------------------------------## -## Added by Martinski W. [2025-Mar-07] ## -##-------------------------------------## -_GetLoginPswdCheckStatusJS_() -{ - if [ ! -s "$PSWD_CHECK_JS" ] ; then echo "0" ; return 0 ; fi - local checkCode - checkCode="$(grep "^var loginPswdCheckStatus =" "$PSWD_CHECK_JS" | awk -F '[ ;]' '{print $4}')" - if [ -z "$checkCode" ] - then echo "0" - else echo "$checkCode" - fi - return 0 -} - -##-------------------------------------## -## Added by Martinski W. [2025-Mar-07] ## -##-------------------------------------## -_UpdateLoginPswdCheckHelper_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi - local checkCode checkMsge prevChkCode - - case "$1" in - InitPWD) - checkCode=0 - checkMsge="Password is EMPTY." - ;; - NoACCESS) - checkCode=1 - checkMsge="Login access is RESTRICTED." - ;; - OldPSWD) - prevChkCode="$(_GetLoginPswdCheckStatusJS_)" - if [ -n "$prevChkCode" ] && [ "$prevChkCode" -gt 1 ] - then - return 0 - else - checkCode=2 - checkMsge="Password is unchanged." - fi - ;; - NewPSWD) - checkCode=3 - checkMsge="Password is NOT verified." - ;; - SUCCESS) - checkCode=4 - checkMsge="Password is verified." - ;; - FAILURE) - checkCode=5 - checkMsge="Password is INVALID." - ;; - UNKNOWN) - prevChkCode="$(_GetLoginPswdCheckStatusJS_)" - if [ -n "$prevChkCode" ] && [ "$prevChkCode" -gt 1 ] - then - return 0 - else - checkCode=6 - checkMsge="UNKNOWN" - fi - ;; - *) ##IGNORE## - return 1 ;; - esac - - _WriteVarDefToPswdCheckJSFile_ "loginPswdCheckStatus" "$checkCode" true - _WriteVarDefToPswdCheckJSFile_ "loginPswdCheckMsgStr" "$checkMsge" -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-07] ## -##----------------------------------------## -_InitCustomSettingsConfig_() -{ - [ ! -d "$SETTINGS_DIR" ] && mkdir -m 755 -p "$SETTINGS_DIR" - - if [ ! -f "$CONFIG_FILE" ] - then - { - echo "FW_New_Update_Notification_Date TBD" - echo "FW_New_Update_Notification_Vers TBD" - echo "FW_New_Update_Postponement_Days=$FW_UpdateDefaultPostponementDays" - echo "FW_New_Update_EMail_Notification $FW_UpdateEMailNotificationDefault" - echo "FW_New_Update_EMail_FormatType=\"${FW_UpdateEMailFormatTypeDefault}\"" - echo "FW_New_Update_Cron_Job_Schedule=\"${FW_Update_CRON_DefaultSchedule}\"" - echo "FW_New_Update_ZIP_Directory_Path=\"${FW_Update_ZIP_DefaultSetupDIR}\"" - echo "FW_New_Update_LOG_Directory_Path=\"${FW_Update_LOG_BASE_DefaultDIR}\"" - echo "FW_New_Update_LOG_Preferred_Path=\"${FW_Update_LOG_BASE_DefaultDIR}\"" - echo "FW_New_Update_EMail_CC_Name=TBD" - echo "FW_New_Update_EMail_CC_Address=TBD" - echo "credentials_base64 TBD" - echo "CheckChangeLog ENABLED" - echo "FW_Update_Check TBD" - echo "Allow_Updates_OverVPN DISABLED" - echo "FW_Allow_Beta_Production_Up ENABLED" - echo "Allow_Script_Auto_Update DISABLED" - echo "Script_Update_Cron_Job_SchedDays=\"${SW_Update_CRON_DefaultSchedDays}\"" - } > "$CONFIG_FILE" - chmod 664 "$CONFIG_FILE" - _UpdateLoginPswdCheckHelper_ InitPWD - return 1 - fi - local retCode=0 preferredPath - - # TEMPORARY Migration Function # - _Migrate_Settings_ - - if ! grep -q "^FW_New_Update_Notification_Date " "$CONFIG_FILE" - then - sed -i "1 i FW_New_Update_Notification_Date TBD" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_New_Update_Notification_Vers " "$CONFIG_FILE" - then - sed -i "2 i FW_New_Update_Notification_Vers TBD" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_New_Update_Postponement_Days=" "$CONFIG_FILE" - then - sed -i "3 i FW_New_Update_Postponement_Days=$FW_UpdateDefaultPostponementDays" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_New_Update_EMail_Notification " "$CONFIG_FILE" - then - sed -i "4 i FW_New_Update_EMail_Notification $FW_UpdateEMailNotificationDefault" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_New_Update_EMail_FormatType=" "$CONFIG_FILE" - then - sed -i "5 i FW_New_Update_EMail_FormatType=\"${FW_UpdateEMailFormatTypeDefault}\"" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_New_Update_Cron_Job_Schedule=" "$CONFIG_FILE" - then - sed -i "6 i FW_New_Update_Cron_Job_Schedule=\"${FW_Update_CRON_DefaultSchedule}\"" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_New_Update_ZIP_Directory_Path=" "$CONFIG_FILE" - then - sed -i "7 i FW_New_Update_ZIP_Directory_Path=\"${FW_Update_ZIP_DefaultSetupDIR}\"" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_New_Update_LOG_Directory_Path=" "$CONFIG_FILE" - then - sed -i "8 i FW_New_Update_LOG_Directory_Path=\"${FW_Update_LOG_BASE_DefaultDIR}\"" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_New_Update_LOG_Preferred_Path=" "$CONFIG_FILE" - then - preferredPath="$(Get_Custom_Setting FW_New_Update_LOG_Directory_Path)" - sed -i "9 i FW_New_Update_LOG_Preferred_Path=\"${preferredPath}\"" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^credentials_base64 " "$CONFIG_FILE" - then - sed -i "10 i credentials_base64 TBD" "$CONFIG_FILE" - _UpdateLoginPswdCheckHelper_ InitPWD - retCode=1 - else - _UpdateLoginPswdCheckHelper_ UNKNOWN - fi - if ! grep -q "^CheckChangeLog " "$CONFIG_FILE" - then - sed -i "11 i CheckChangeLog ENABLED" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_Update_Check " "$CONFIG_FILE" - then - sed -i "12 i FW_Update_Check TBD" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^Allow_Updates_OverVPN " "$CONFIG_FILE" - then - sed -i "13 i Allow_Updates_OverVPN DISABLED" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^FW_Allow_Beta_Production_Up " "$CONFIG_FILE" - then - sed -i "14 i FW_Allow_Beta_Production_Up ENABLED" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^Allow_Script_Auto_Update " "$CONFIG_FILE" - then - sed -i "15 i Allow_Script_Auto_Update DISABLED" "$CONFIG_FILE" - retCode=1 - fi - if ! grep -q "^Script_Update_Cron_Job_SchedDays=" "$CONFIG_FILE" - then - sed -i "16 i Script_Update_Cron_Job_SchedDays=\"${SW_Update_CRON_DefaultSchedDays}\"" "$CONFIG_FILE" - retCode=1 - fi - dos2unix "$CONFIG_FILE" - chmod 664 "$CONFIG_FILE" - - return "$retCode" -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-05] ## -##----------------------------------------## -Get_Custom_Setting() -{ - if [ $# -eq 0 ] || [ -z "$1" ]; then echo "**ERROR**"; return 1; fi - [ ! -d "$SETTINGS_DIR" ] && mkdir -m 755 -p "$SETTINGS_DIR" - - local setting_value="" setting_type="$1" default_value="TBD" - [ $# -gt 1 ] && default_value="$2" - - if [ -f "$CONFIG_FILE" ] - then - case "$setting_type" in - "ROGBuild" | "TUFBuild" | \ - "credentials_base64" | \ - "CheckChangeLog" | \ - "FW_Update_Check" | \ - "Allow_Updates_OverVPN" | \ - "FW_Allow_Beta_Production_Up" | \ - "FW_Auto_Backupmon" | \ - "Allow_Script_Auto_Update" | \ - "FW_New_Update_EMail_Notification" | \ - "FW_New_Update_Notification_Date" | \ - "FW_New_Update_Notification_Vers") - setting_value="$(grep "^${setting_type} " "$CONFIG_FILE" | awk -F ' ' '{print $2}')" - ;; - "FW_New_Update_Postponement_Days" | \ - "FW_New_Update_Changelog_Approval" | \ - "FW_New_Update_Expected_Run_Date" | \ - "FW_New_Update_Cron_Job_Schedule" | \ - "Script_Update_Cron_Job_SchedDays" | \ - "FW_New_Update_ZIP_Directory_Path" | \ - "FW_New_Update_LOG_Directory_Path" | \ - "FW_New_Update_LOG_Preferred_Path" | \ - "FW_New_Update_EMail_FormatType" | \ - "FW_New_Update_EMail_CC_Name" | \ - "FW_New_Update_EMail_CC_Address") - grep -q "^${setting_type}=" "$CONFIG_FILE" && \ - setting_value="$(grep "^${setting_type}=" "$CONFIG_FILE" | awk -F '=' '{print $2}' | sed "s/['\"]//g")" - ;; - *) - setting_value="**ERROR**" - ;; - esac - if [ -z "$setting_value" ] - then echo "$default_value" - else echo "$setting_value" - fi - else - echo "$default_value" - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-20] ## -##----------------------------------------## -Update_Custom_Settings() -{ - if [ $# -lt 2 ] || [ -z "$1" ] || [ -z "$2" ] ; then return 1 ; fi - - local fixedVal oldVal="" - local setting_type="$1" setting_value="$2" - - # Check if the directory exists, and if not, create it # - [ ! -d "$SETTINGS_DIR" ] && mkdir -m 755 -p "$SETTINGS_DIR" - - case "$setting_type" in - "ROGBuild" | "TUFBuild" | \ - "credentials_base64" | \ - "CheckChangeLog" | \ - "FW_Update_Check" | \ - "Allow_Updates_OverVPN" | \ - "FW_Allow_Beta_Production_Up" | \ - "FW_Auto_Backupmon" | \ - "Allow_Script_Auto_Update" | \ - "FW_New_Update_EMail_Notification" | \ - "FW_New_Update_Notification_Date" | \ - "FW_New_Update_Notification_Vers") - if [ -f "$CONFIG_FILE" ] - then - if [ "$(grep -c "^$setting_type" "$CONFIG_FILE")" -gt 0 ] - then - if [ "$setting_value" != "$(grep "^$setting_type" "$CONFIG_FILE" | cut -f2 -d' ')" ] - then - sed -i "s/^$setting_type.*/$setting_type $setting_value/" "$CONFIG_FILE" - fi - else - echo "$setting_type $setting_value" >> "$CONFIG_FILE" - fi - else - echo "$setting_type $setting_value" > "$CONFIG_FILE" - fi - ;; - "FW_New_Update_Postponement_Days" | \ - "FW_New_Update_Changelog_Approval" | \ - "FW_New_Update_Expected_Run_Date" | \ - "FW_New_Update_Cron_Job_Schedule" | \ - "Script_Update_Cron_Job_SchedDays" | \ - "FW_New_Update_ZIP_Directory_Path" | \ - "FW_New_Update_LOG_Directory_Path" | \ - "FW_New_Update_LOG_Preferred_Path" | \ - "FW_New_Update_EMail_FormatType" | \ - "FW_New_Update_EMail_CC_Name" | \ - "FW_New_Update_EMail_CC_Address") - if [ -f "$CONFIG_FILE" ] - then - if grep -q "^${setting_type}=" "$CONFIG_FILE" - then - oldVal="$(grep "^${setting_type}=" "$CONFIG_FILE" | awk -F '=' '{print $2}' | sed "s/['\"]//g")" - if [ -z "$oldVal" ] || [ "$oldVal" != "$setting_value" ] - then - fixedVal="$(echo "$setting_value" | sed 's/[\/.,*-]/\\&/g')" - sed -i "s/${setting_type}=.*/${setting_type}=\"${fixedVal}\"/" "$CONFIG_FILE" - fi - else - echo "$setting_type=\"${setting_value}\"" >> "$CONFIG_FILE" - fi - else - echo "$setting_type=\"${setting_value}\"" > "$CONFIG_FILE" - fi - if [ "$setting_type" = "FW_New_Update_Postponement_Days" ] - then - FW_UpdatePostponementDays="$setting_value" - # - elif [ "$setting_type" = "FW_New_Update_Expected_Run_Date" ] - then - FW_UpdateExpectedRunDate="$setting_value" - # - elif [ "$setting_type" = "FW_New_Update_EMail_FormatType" ] - then - sendEMailFormaType="$setting_value" - [ "$sendEMailFormaType" = "HTML" ] && \ - isEMailFormatHTML=true || isEMailFormatHTML=false - # - elif [ "$setting_type" = "FW_New_Update_EMail_CC_Name" ] - then - sendEMail_CC_Name="$setting_value" - # - elif [ "$setting_type" = "FW_New_Update_EMail_CC_Address" ] - then - sendEMail_CC_Address="$setting_value" - # - elif [ "$setting_type" = "FW_New_Update_Cron_Job_Schedule" ] - then - FW_UpdateCronJobSchedule="$setting_value" - _WebUI_AutoScriptUpdateCronSchedule_ - _WebUI_AutoFWUpdateCheckCronSchedule_ - # - elif [ "$setting_type" = "Script_Update_Cron_Job_SchedDays" ] - then - ScriptUpdateCronSchedDays="$setting_value" - _WebUI_AutoScriptUpdateCronSchedule_ - # - elif [ "$setting_type" = "FW_New_Update_ZIP_Directory_Path" ] - then - _SetUp_FW_UpdateZIP_DirectoryPaths_ "$setting_value" - # - elif [ "$setting_type" = "FW_New_Update_LOG_Directory_Path" ] - then - _SetUp_FW_UpdateLOG_DirectoryPaths_ "$setting_value" - fi - ;; - *) - # Generic handling for arbitrary settings # - if grep -q "^${setting_type}=" "$CONFIG_FILE" - then - oldVal="$(grep "^${setting_type}=" "$CONFIG_FILE" | awk -F '=' '{print $2}' | sed "s/['\"]//g")" - if [ -z "$oldVal" ] || [ "$oldVal" != "$setting_value" ] - then - fixedVal="$(echo "$setting_value" | sed 's/[\/&]/\\&/g')" - sed -i "s/^${setting_type}=.*/${setting_type}=\"${fixedVal}\"/" "$CONFIG_FILE" - fi - else - echo "${setting_type}=\"${setting_value}\"" >> "$CONFIG_FILE" - fi - ;; - esac - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Jun-04] ## -##----------------------------------------## -Delete_Custom_Settings() -{ - if [ $# -lt 1 ] || [ -z "$1" ] || [ ! -f "$CONFIG_FILE" ] - then return 1 ; fi - - local setting_type="$1" - sed -i "/^${setting_type}[ =]/d" "$CONFIG_FILE" - return $? -} - -##------------------------------------------## -## Modified by ExtremeFiretop [2024-Dec-21] ## -##------------------------------------------## -_GetAllNodeSettings_() -{ - if [ $# -lt 2 ] || [ -z "$1" ] || [ -z "$2" ] - then echo "**ERROR**" ; return 1; fi - - ## Node Setting KEY="Node_{MACaddress}_{keySuffix}" ## - local fullKeyName="Node_${1}_${2}" - local setting_value="TBD" matched_lines - - # Ensure the settings directory exists # - [ ! -d "$SETTINGS_DIR" ] && mkdir -m 755 -p "$SETTINGS_DIR" - - if [ -f "$CONFIG_FILE" ] - then - matched_lines="$(grep -E "^${fullKeyName}=.*" "$CONFIG_FILE")" - if [ -n "$matched_lines" ] - then - # Extract the value from the first matched line # - setting_value="$(echo "$matched_lines" | head -n 1 | awk -F '=' '{print $2}' | tr -d '"')" - fi - fi - echo "$setting_value" -} - -##-------------------------------------## -## Added by Martinski W. [2025-Feb-23] ## -##-------------------------------------## -extCheckRETvarID=0x00 -extCheckZIPdirID=0x01 -extCheckLOGdirID=0x02 -extCheckALLvarID=0x0F -extCheckZIPdirOK=true -extCheckLOGdirOK=true -extCheckRETvarOK=true -extCheckZIPdirMG="OK" -extCheckLOGdirMG="OK" -extCheckRETvarMG="OK" - -##-------------------------------------## -## Added by Martinski W. [2025-Feb-25] ## -##-------------------------------------## -_WebUI_FW_UpdateZIPDirPathDefault_() -{ - local defltDirPath="/home/root" - if [ -n "$USBMountPoint" ] && \ - _ValidateUSBMountPoint_ "$FW_ZIP_BASE_DIR" - then defltDirPath="$FW_ZIP_BASE_DIR" ; fi - _WriteVarDefToHelperJSFile_ "defaultFWUpdateZIPdirPath" "$defltDirPath" -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-25] ## -##----------------------------------------## -_InitHelperJSFile_() -{ - ! "$mountWebGUI_OK" && return 0 - - [ ! -s "$HELPER_JSFILE" ] && \ - { - echo "var externalCheckID = 0x00;" - echo "var externalCheckOK = true;" - echo "var externalCheckMsg = '';" - } > "$HELPER_JSFILE" - - _WebUI_FW_UpdateZIPDirPathDefault_ - _WebUI_SetEmailConfigFileFromAMTM_ - _WebUI_AutoScriptUpdateCronSchedule_ - _WebUI_AutoFWUpdateCheckCronSchedule_ -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-25] ## -##----------------------------------------## -_UpdateHelperJSFile_() -{ - if [ $# -lt 2 ] || \ - [ -z "$1" ] || [ -z "$2" ] || \ - ! "$mountWebGUI_OK" - then return 1; fi - - local extCheckMsg="" - if [ $# -gt 2 ] && [ -n "$3" ] - then extCheckMsg="$3" ; fi - - if [ "$(($1 & extCheckZIPdirID))" -gt 0 ] - then - extCheckZIPdirOK="$2" - extCheckZIPdirMG="$extCheckMsg" - fi - if [ "$(($1 & extCheckLOGdirID))" -gt 0 ] - then - extCheckLOGdirOK="$2" - extCheckLOGdirMG="$extCheckMsg" - fi - - if [ "$1" = "$extCheckALLvarID" ] || \ - [ "$extCheckZIPdirOK" = "$extCheckLOGdirOK" ] - then - extCheckRETvarOK="$extCheckZIPdirOK" - extCheckRETvarID="$((extCheckZIPdirID | extCheckLOGdirID))" - if "$extCheckZIPdirOK" - then - extCheckRETvarMG="$extCheckZIPdirMG" - else - extCheckRETvarMG="${extCheckZIPdirMG}\n\n${extCheckLOGdirMG}" - fi - elif ! "$extCheckZIPdirOK" - then - extCheckRETvarOK="$extCheckZIPdirOK" - extCheckRETvarID="$extCheckZIPdirID" - extCheckRETvarMG="$extCheckZIPdirMG" - elif ! "$extCheckLOGdirOK" - then - extCheckRETvarOK="$extCheckLOGdirOK" - extCheckRETvarID="$extCheckLOGdirID" - extCheckRETvarMG="$extCheckLOGdirMG" - fi - - { - echo "var externalCheckID = ${extCheckRETvarID};" - echo "var externalCheckOK = ${extCheckRETvarOK};" - echo "var externalCheckMsg = '${extCheckRETvarMG}';" - } > "$HELPER_JSFILE" - - _WebUI_FW_UpdateZIPDirPathDefault_ - _WebUI_SetEmailConfigFileFromAMTM_ - _WebUI_AutoScriptUpdateCronSchedule_ - _WebUI_AutoFWUpdateCheckCronSchedule_ -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-23] ## -##----------------------------------------## -_Validate_FW_UpdateLOG_DirectoryPath_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi - - local updateHelperJS=false - if [ $# -eq 2 ] && [ "$2" = "true" ] - then updateHelperJS=true ; fi - - if [ ! -d "$1" ] - then - if "$updateHelperJS" - then - checkErrorMsg="The directory path for F/W update log files is NOT found:\n[$1]" - _UpdateHelperJSFile_ "$extCheckLOGdirID" "false" "$checkErrorMsg" - fi - Say "${REDct}**ERROR**${NOct}: Directory path [${REDct}${1}${NOct}] for F/W update log files is NOT found." - _WaitForEnterKey_ - return 1 - fi - - if [ "$1" = "$FW_LOG_DIR" ] || [ "$1" = "$FW_LOG_BASE_DIR" ] - then - _UpdateHelperJSFile_ "$extCheckLOGdirID" "true" - return 0 - fi - - local newFullDirPath="" newBaseDirPath="$1" - - if echo "$newBaseDirPath" | grep -qE "/${FW_LOG_SUBDIR}$" - then newFullDirPath="$newBaseDirPath" - else newFullDirPath="${newBaseDirPath}/$FW_LOG_SUBDIR" - fi - mkdir -p -m 755 "$newFullDirPath" 2>/dev/null - if [ ! -d "$newFullDirPath" ] - then - if "$updateHelperJS" - then - checkErrorMsg="The directory path for F/W update log files cannot be created:\n[$newFullDirPath]" - _UpdateHelperJSFile_ "$extCheckLOGdirID" "false" "$checkErrorMsg" - fi - Say "${REDct}**ERROR**${NOct}: Could NOT create directory path [${REDct}${newFullDirPath}${NOct}] for F/W update log files." - _WaitForEnterKey_ - return 1 - fi - # Move any existing log files to new directory # - mv -f "${FW_LOG_DIR}"/*.log "$newFullDirPath" 2>/dev/null - # Remove now the obsolete directory path # - rm -fr "${FW_LOG_DIR:?}" - # Update the log directory paths after validation # - Update_Custom_Settings FW_New_Update_LOG_Directory_Path "$newBaseDirPath" - Update_Custom_Settings FW_New_Update_LOG_Preferred_Path "$newBaseDirPath" - _UpdateHelperJSFile_ "$extCheckLOGdirID" "true" - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-23] ## -##----------------------------------------## -_Set_FW_UpdateLOG_DirectoryPath_() -{ - local newLOG_BaseDirPath="$FW_LOG_BASE_DIR" - - while true - do - printf "\nEnter the directory path where the subdirectory [${GRNct}${FW_LOG_SUBDIR}${NOct}] will be located.\n" - printf "[${theLGExitStr}]\n" - printf "[Current Base Path: ${GRNct}${FW_LOG_BASE_DIR}${NOct}]: " - read -r userInput - - if [ -z "$userInput" ] ; then break ; fi - if echo "$userInput" | grep -qE "^(e|exit|Exit)$" ; then return 1 ; fi - - if echo "$userInput" | grep -q '/$' - then userInput="${userInput%/*}" ; fi - - if echo "$userInput" | grep -q '//' || \ - echo "$userInput" | grep -q '/$' || \ - ! echo "$userInput" | grep -q '^/' || \ - [ "${#userInput}" -lt 4 ] || \ - [ "$(echo "$userInput" | awk -F '/' '{print NF-1}')" -lt 2 ] - then - printf "\n${REDct}INVALID input.${NOct}\n" - _WaitForEnterKey_ - clear - continue - fi - - if [ -d "$userInput" ] - then newLOG_BaseDirPath="$userInput" ; break ; fi - - rootDir="${userInput%/*}" - if [ ! -d "$rootDir" ] - then - printf "\n${REDct}**ERROR**${NOct}: Root directory path [${REDct}${rootDir}${NOct}] does NOT exist.\n\n" - printf "\n${REDct}INVALID input.${NOct}\n" - _WaitForEnterKey_ - clear - continue - fi - - printf "The directory path '${REDct}${userInput}${NOct}' does NOT exist.\n\n" - if ! _WaitForYESorNO_ "Do you want to create it now" - then - printf "Directory was ${REDct}NOT${NOct} created.\n\n" - else - mkdir -m 755 "$userInput" 2>/dev/null - if [ -d "$userInput" ] - then newLOG_BaseDirPath="$userInput" ; break - else printf "\n${REDct}**ERROR**${NOct}: Could NOT create directory [${REDct}${userInput}${NOct}].\n\n" - fi - fi - done - - if [ -d "$newLOG_BaseDirPath" ] - then - if ! _Validate_FW_UpdateLOG_DirectoryPath_ "$newLOG_BaseDirPath" - then return 1 - fi - echo "The directory path for the log files was updated successfully." - _WaitForEnterKey_ "$logsMenuReturnPromptStr" - fi - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-23] ## -##----------------------------------------## -_Validate_FW_UpdateZIP_DirectoryPath_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi - - local updateHelperJS=false - if [ $# -eq 2 ] && [ "$2" = "true" ] - then updateHelperJS=true ; fi - - if [ ! -d "$1" ] - then - if "$updateHelperJS" - then - checkErrorMsg="The directory path for F/W update files is NOT found:\n[$1]" - _UpdateHelperJSFile_ "$extCheckZIPdirID" "false" "$checkErrorMsg" - fi - Say "${REDct}**ERROR**${NOct}: Directory path [${REDct}${1}${NOct}] for F/W update files is NOT found." - _WaitForEnterKey_ - return 1 - fi - - if [ "$1" = "$FW_ZIP_DIR" ] || [ "$1" = "$FW_ZIP_BASE_DIR" ] - then - _UpdateHelperJSFile_ "$extCheckZIPdirID" "true" - return 0 - fi - - local newFullDirPath="" newBaseDirPath="$1" - - if echo "$newBaseDirPath" | grep -qE "/${FW_ZIP_SUBDIR}$" - then newFullDirPath="$newBaseDirPath" - else newFullDirPath="${newBaseDirPath}/$FW_ZIP_SUBDIR" - fi - mkdir -p -m 755 "$newFullDirPath" 2>/dev/null - if [ ! -d "$newFullDirPath" ] - then - if "$updateHelperJS" - then - checkErrorMsg="The directory path for F/W update files cannot be created:\n[$newFullDirPath]" - _UpdateHelperJSFile_ "$extCheckZIPdirID" "false" "$checkErrorMsg" - fi - Say "${REDct}**ERROR**${NOct}: Could NOT create directory path [${REDct}${newFullDirPath}${NOct}] for F/W update files." - _WaitForEnterKey_ - return 1 - fi - # Remove now the obsolete directory path # - rm -fr "${FW_ZIP_DIR:?}" - rm -f "${newFullDirPath}"/*.zip "${newFullDirPath}"/*.sha256 - Update_Custom_Settings FW_New_Update_ZIP_Directory_Path "$newBaseDirPath" - _UpdateHelperJSFile_ "$extCheckZIPdirID" "true" - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-23] ## -##----------------------------------------## -_Set_FW_UpdateZIP_DirectoryPath_() -{ - local newZIP_BaseDirPath="$FW_ZIP_BASE_DIR" - - while true - do - printf "\nEnter the directory path where the update subdirectory [${GRNct}${FW_ZIP_SUBDIR}${NOct}] will be located.\n" - if [ -n "$USBMountPoint" ] && _ValidateUSBMountPoint_ "$FW_ZIP_BASE_DIR" - then - printf "Default directory for USB-attached drive: [${GRNct}${FW_ZIP_BASE_DIR}${NOct}]\n" - else - printf "Default directory for 'Local' storage is: [${GRNct}/home/root${NOct}]\n" - fi - printf "\n[${theADExitStr}]\n" - printf "[Current Base Path: ${GRNct}${FW_ZIP_BASE_DIR}${NOct}]: " - read -r userInput - - if [ -z "$userInput" ] ; then break ; fi - if echo "$userInput" | grep -qE "^(e|E|exit|Exit)$" ; then return 1 ; fi - - if echo "$userInput" | grep -q '/$' - then userInput="${userInput%/*}" ; fi - - if echo "$userInput" | grep -q '//' || \ - echo "$userInput" | grep -q '/$' || \ - ! echo "$userInput" | grep -q '^/' || \ - [ "${#userInput}" -lt 4 ] || \ - [ "$(echo "$userInput" | awk -F '/' '{print NF-1}')" -lt 2 ] - then - printf "\n${REDct}INVALID input.${NOct}\n" - _WaitForEnterKey_ - clear - continue - fi - - if [ -d "$userInput" ] - then newZIP_BaseDirPath="$userInput" ; break ; fi - - rootDir="${userInput%/*}" - if [ ! -d "$rootDir" ] - then - printf "\n${REDct}**ERROR**${NOct}: Root directory path [${REDct}${rootDir}${NOct}] does NOT exist.\n\n" - printf "\n${REDct}INVALID input.${NOct}\n" - _WaitForEnterKey_ - clear - continue - fi - - printf "The directory path '${REDct}${userInput}${NOct}' does NOT exist.\n\n" - if ! _WaitForYESorNO_ "Do you want to create it now" - then - printf "Directory was ${REDct}NOT${NOct} created.\n\n" - else - mkdir -m 755 "$userInput" 2>/dev/null - if [ -d "$userInput" ] - then newZIP_BaseDirPath="$userInput" ; break - else printf "\n${REDct}**ERROR**${NOct}: Could NOT create directory [${REDct}${userInput}${NOct}].\n\n" - fi - fi - done - - if [ -d "$newZIP_BaseDirPath" ] - then - if ! _Validate_FW_UpdateZIP_DirectoryPath_ "$newZIP_BaseDirPath" - then return 1 - fi - if "$isGNUtonFW" - then - echo "The directory path for the F/W update file was updated successfully." - else - echo "The directory path for the F/W ZIP file was updated successfully." - fi - keepWfile=0 - _WaitForEnterKey_ "$advnMenuReturnPromptStr" - fi - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-15] ## -##----------------------------------------## -## Function to migrate specific settings from old values to new standardized values. -## This function is meant to be only TEMPORARY. -## We should be safe to remove it after 3 months, or 5 version releases, -## whichever comes first. Similar to the migration function removed in v1.0.9 -##-----------------------------------------------------------------------------------## -_Migrate_Settings_() -{ - [ ! -s "$CONFIG_FILE" ] && return 1 - - ## Migrate Setting from [y|Y|n|N] to [ENABLED|DISABLED] ## - ROGBuild_Value="$(Get_Custom_Setting ROGBuild)" - if [ "$ROGBuild_Value" != "TBD" ] - then - case "$ROGBuild_Value" in - y|Y) New_ROGBuild_Value="ENABLED" ;; - n|N) New_ROGBuild_Value="DISABLED" ;; - *) - New_ROGBuild_Value="" - ! echo "$ROGBuild_Value" | grep -qE "^(ENABLED|DISABLED)$" && \ - Say "ROGBuild has a unknown value: '$ROGBuild_Value'. Skipping migration for this setting." - ;; - esac - if [ -n "$New_ROGBuild_Value" ] - then - if Update_Custom_Settings ROGBuild "$New_ROGBuild_Value" - then - Say "ROGBuild setting was successfully migrated to '$New_ROGBuild_Value'." - else - Say "Error occurred while migrating ROGBuild setting to '$New_ROGBuild_Value'." - fi - fi - fi - - ## Migrate Setting from [y|Y|n|N] to [ENABLED|DISABLED] ## - TUFBuild_Value="$(Get_Custom_Setting TUFBuild)" - if [ "$TUFBuild_Value" != "TBD" ] - then - case "$TUFBuild_Value" in - y|Y) New_TUFBuild_Value="ENABLED" ;; - n|N) New_TUFBuild_Value="DISABLED" ;; - *) - New_TUFBuild_Value="" - ! echo "$TUFBuild_Value" | grep -qE "^(ENABLED|DISABLED)$" && \ - Say "TUFBuild has a unknown value: '$TUFBuild_Value'. Skipping migration for this setting." - ;; - esac - if [ -n "$New_TUFBuild_Value" ] - then - if Update_Custom_Settings TUFBuild "$New_TUFBuild_Value" - then - Say "TUFBuild setting was successfully migrated to '$New_TUFBuild_Value'." - else - Say "Error occurred while migrating TUFBuild setting to '$New_TUFBuild_Value'." - fi - fi - fi - - ## Migrate Setting from [true|false] to [ENABLED|DISABLED] ## - EMailNotif_Value="$(grep '^FW_New_Update_EMail_Notification=' "$CONFIG_FILE" | cut -d'=' -f2 | tr -d '"')" - if [ -n "$EMailNotif_Value" ] && [ "$EMailNotif_Value" != "TBD" ] - then - case "$EMailNotif_Value" in - true|TRUE|True) New_EMailNotif_Value="ENABLED" ;; - false|FALSE|False) New_EMailNotif_Value="DISABLED" ;; - *) - New_EMailNotif_Value="" - ! echo "$EMailNotif_Value" | grep -qE "^(ENABLED|DISABLED)$" && \ - Say "FW_New_Update_EMail_Notification has a unknown value: '$EMailNotif_Value'. Skipping migration for this setting." - ;; - esac - if [ -n "$New_EMailNotif_Value" ] - then - sed -i '/^FW_New_Update_EMail_Notification .*/d' "$CONFIG_FILE" - sed -i "s/^FW_New_Update_EMail_Notification=.*/FW_New_Update_EMail_Notification $New_EMailNotif_Value/" "$CONFIG_FILE" - if [ $? -eq 0 ] - then - sendEMailNotificationsFlag="$New_EMailNotif_Value" - Say "EMail_Notification setting was successfully migrated to $New_EMailNotif_Value." - else - Say "Error occurred while migrating EMail_Notification setting to $New_EMailNotif_Value." - fi - fi - fi -} - -##------------------------------------------## -## Modified by ExtremeFiretop [2024-Jan-27] ## -##------------------------------------------## -# NOTE: -# Depending on available RAM & storage capacity of the -# target router, it may be required to have USB-attached -# storage for the ZIP file so that it can be downloaded -# in a separate directory from the firmware bin file. -#----------------------------------------------------------- -readonly FW_LOG_SUBDIR="${ScriptDirNameD}/logs" -readonly FW_BIN_SUBDIR="${ScriptDirNameD}/$FW_FileName" -readonly FW_ZIP_SUBDIR="${ScriptDirNameD}/$FW_FileName" - -FW_BIN_BASE_DIR="/home/root" -FW_BIN_DIR="${FW_BIN_BASE_DIR}/$FW_BIN_SUBDIR" - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-15] ## -##----------------------------------------## -_SetUp_FW_UpdateZIP_DirectoryPaths_ -_SetUp_FW_UpdateLOG_DirectoryPaths_ - -##----------------------------------------## -## Modified by Martinski W. [2023-Nov-24] ## -##----------------------------------------## -# The built-in F/W hook script file to be used for -# setting up persistent jobs to run after a reboot. -readonly hookScriptFName="services-start" -readonly hookScriptFPath="${SCRIPTS_PATH}/$hookScriptFName" -readonly hookScriptTagStr="#Added by $ScriptFNameTag#" - -# Postponement Days for F/W Update Check # -FW_UpdatePostponementDays="$(Get_Custom_Setting FW_New_Update_Postponement_Days)" -FW_UpdateExpectedRunDate="$(Get_Custom_Setting FW_New_Update_Expected_Run_Date)" - -##----------------------------------------## -## Modified by Martinski W. [2024-Feb-18] ## -##----------------------------------------## -# F/W Update Email Notifications # -isEMailFormatHTML=true -isEMailConfigEnabledInAMTM=false -sendEMailFormaType="$(Get_Custom_Setting FW_New_Update_EMail_FormatType)" -sendEMailNotificationsFlag="$(Get_Custom_Setting FW_New_Update_EMail_Notification)" -sendEMail_CC_Name="$(Get_Custom_Setting FW_New_Update_EMail_CC_Name)" -sendEMail_CC_Address="$(Get_Custom_Setting FW_New_Update_EMail_CC_Address)" -if [ "$sendEMailFormaType" = "HTML" ] -then isEMailFormatHTML=true -else isEMailFormatHTML=false -fi - -##----------------------------------------## -## Modified by Martinski W. [2024-Nov-27] ## -##----------------------------------------## -# Define the CRON job command to execute # -# Define the hook script file to be used # -ScriptAutoUpdateSetting="$(Get_Custom_Setting Allow_Script_Auto_Update)" -ScriptUpdateCronSchedDays="$(Get_Custom_Setting Script_Update_Cron_Job_SchedDays)" - -readonly SCRIPT_UP_CRON_JOB_RUN="sh $ScriptFilePath checkupdates" -readonly SCRIPT_UP_CRON_JOB_TAG="${ScriptFNameTag}_ScriptUpdate" -readonly DAILY_SCRIPT_UPDATE_CHECK_JOB="sh $ScriptFilePath scriptAUCronJob & $hookScriptTagStr" -readonly DAILY_SCRIPT_UPDATE_CHECK_HOOK="[ -f $ScriptFilePath ] && $DAILY_SCRIPT_UPDATE_CHECK_JOB" - -# Define the CRON job command to execute # -FW_UpdateCronJobSchedule="$(Get_Custom_Setting FW_New_Update_Cron_Job_Schedule)" -readonly CRON_JOB_RUN="sh $ScriptFilePath run_now" -readonly CRON_JOB_TAG_OLD="$ScriptFNameTag" -readonly CRON_JOB_TAG="${ScriptFNameTag}_FWUpdate" -readonly CRON_SCRIPT_JOB="sh $ScriptFilePath addCronJob & $hookScriptTagStr" -readonly CRON_SCRIPT_HOOK="[ -f $ScriptFilePath ] && $CRON_SCRIPT_JOB" - -# Define post-reboot run job command to execute # -readonly POST_REBOOT_SCRIPT_JOB="sh $ScriptFilePath postRebootRun & $hookScriptTagStr" -readonly POST_REBOOT_SCRIPT_HOOK="[ -f $ScriptFilePath ] && $POST_REBOOT_SCRIPT_JOB" - -# Define post-update email notification job command to execute # -readonly POST_UPDATE_EMAIL_SCRIPT_JOB="sh $ScriptFilePath postUpdateEmail & $hookScriptTagStr" -readonly POST_UPDATE_EMAIL_SCRIPT_HOOK="[ -f $ScriptFilePath ] && $POST_UPDATE_EMAIL_SCRIPT_JOB" - -if [ -d "$FW_LOG_DIR" ] -then - # Log rotation - delete logs older than 30 days # - /usr/bin/find -L "$FW_LOG_DIR" -name '*.log' -mtime +30 -exec rm {} \; -fi - -##----------------------------------------## -## Modified by Martinski W. [2024-Jan-27] ## -##----------------------------------------## -#------------------------------------------------------------------------------------------- -# This code is in case the user-selected USB mount point isn't available anymore. -# If the USB drive is selected as the log location but it goes offline for some reason, -# any call to the "Say" function creates a new '/tmp/mnt/XXXX' directory. -# In such a case where the USB drive is unmounted, we need to change the log directory -# back to a local directory. First if-statement executes first and updates to local 'jffs' -# directory if no USB drives are found. If ANY DefaultUSBMountPoint found, then move the -# log files from their local jffs location to the default mount location. -# We don't know the user selected yet because it's local at this time and was changed -# by the else statement. Remove the old log directory location from jffs, and update the -# settings file again to the new default again. This creates a semi-permanent switch which -# can reset back to default if the user-selected mount points aren't valid anymore. -#------------------------------------------------------------------------------------------- -UserSelectedLogPath="$(Get_Custom_Setting FW_New_Update_LOG_Directory_Path)" -if [ ! -d "$UserSelectedLogPath" ] || [ ! -r "$UserSelectedLogPath" ]; then - Update_Custom_Settings FW_New_Update_LOG_Directory_Path "$ADDONS_PATH" -fi - -UserPreferredLogPath="$(Get_Custom_Setting FW_New_Update_LOG_Preferred_Path)" -if echo "$UserPreferredLogPath" | grep -qE "^(/tmp/mnt/|/tmp/opt/|/opt/)" && \ - _ValidateUSBMountPoint_ "$UserPreferredLogPath" && \ - [ "$UserPreferredLogPath" != "$FW_LOG_BASE_DIR" ] -then - mv -f "${FW_LOG_DIR}"/*.log "${UserPreferredLogPath}/$FW_LOG_SUBDIR" 2>/dev/null - rm -fr "${FW_LOG_DIR:?}" - Update_Custom_Settings FW_New_Update_LOG_Directory_Path "$UserPreferredLogPath" -fi - -##-------------------------------------## -## Added by Martinski W. [2025-Feb-12] ## -##-------------------------------------## -_Check_WebGUI_Page_Exists_() -{ - local webPageStr webPageFile theWebPage - - if [ ! -f "$TEMP_MENU_TREE" ] - then echo "NONE" ; return 1 ; fi - - theWebPage="NONE" - webPageStr="$(grep -E -m1 "^$webPageLineRegExp" "$TEMP_MENU_TREE")" - if [ -n "$webPageStr" ] - then - webPageFile="$(echo "$webPageStr" | grep -owE "$webPageFileRegExp" | head -n1)" - if [ -n "$webPageFile" ] && [ -s "${SHARED_WEB_DIR}/$webPageFile" ] - then theWebPage="$webPageFile" ; fi - fi - echo "$theWebPage" -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-12] ## -##----------------------------------------## -_GetWebUIPage_() -{ - local webPageFile webPagePath webPageTemp - - webPageFile="$(_Check_WebGUI_Page_Exists_)" - - for index in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 - do - webPageTemp="user${index}.asp" - webPagePath="${SHARED_WEB_DIR}/$webPageTemp" - - if [ -s "$webPagePath" ] && \ - [ "$(md5sum < "$1")" = "$(md5sum < "$webPagePath")" ] - then - webPageFile="$webPageTemp" - break - elif [ "$webPageFile" = "NONE" ] && [ ! -s "$webPagePath" ] - then - webPageFile="$webPageTemp" - fi - done - echo "$webPageFile" -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-11] ## -##----------------------------------------## -_Mount_WebUI_() -{ - if [ ! -f "$SCRIPT_WEB_ASP_PATH" ] - then - Say "${CRITct}**ERROR**${NOct}: The WebUI page file for $SCRIPT_NAME is NOT found." - return 1 - fi - local webPageFile - - Say "Mounting WebUI page for ${SCRIPT_NAME}..." - - eval exec "$WEBUI_LOCKFD>$WEBUI_LOCKFILE" - flock -x "$WEBUI_LOCKFD" - - webPageFile="$(_GetWebUIPage_ "$SCRIPT_WEB_ASP_PATH")" - if [ -z "$webPageFile" ] || [ "$webPageFile" = "NONE" ] - then - Say "${CRITct}**ERROR**${NOct}: Unable to mount the $SCRIPT_NAME WebUI page." - flock -u "$WEBUI_LOCKFD" - return 1 - fi - - cp -fp "$SCRIPT_WEB_ASP_PATH" "${SHARED_WEB_DIR}/$webPageFile" - echo "$SCRIPT_NAME" > "${SHARED_WEB_DIR}/$(echo "$webPageFile" | cut -f1 -d'.').title" - - if [ ! -f "$TEMP_MENU_TREE" ] - then cp -fp "$ORIG_MENU_TREE" "$TEMP_MENU_TREE" - fi - sed -i "/url: \"$webPageFile\", tabName: \"$SCRIPT_NAME\"/d" "$TEMP_MENU_TREE" - - # Insert new page tab in the 'Administration' menu # - sed -i "/url: \"Advanced_FirmwareUpgrade_Content.asp\", tabName:/a {url: \"$webPageFile\", tabName: \"$SCRIPT_NAME\"}," "$TEMP_MENU_TREE" - - umount "$ORIG_MENU_TREE" 2>/dev/null - mount -o bind "$TEMP_MENU_TREE" "$ORIG_MENU_TREE" - flock -u "$WEBUI_LOCKFD" - - Say "${GRNct}$SCRIPT_NAME WebUI page was mounted as $webPageFile successfully." - return 0 -} - -##------------------------------------------## -## Modified by ExtremeFiretop [2025-Apr-07] ## -##------------------------------------------## -_CheckFor_WebGUI_Page_() -{ - if "$mountWebGUI_OK" && \ - [ "$(_Check_WebGUI_Page_Exists_)" = "NONE" ] - then - updatedWebUIPage=false - # Only try to download if the local .asp file does NOT exist: - if [ ! -f "$SCRIPT_WEB_ASP_FILE" ] - then - if _CurlFileDownload_ "$SCRIPT_WEB_ASP_FILE" "$SCRIPT_WEB_ASP_PATH" - then - chmod 664 "$SCRIPT_WEB_ASP_PATH" - theWebPage="$(_GetWebUIPage_ "$SCRIPT_WEB_ASP_PATH")" - if [ -n "$theWebPage" ] && [ "$theWebPage" != "NONE" ] - then - sed -i "/url: \"$theWebPage\", tabName: \"$SCRIPT_NAME\"/d" "$TEMP_MENU_TREE" - rm -f "${SHARED_WEB_DIR}/$theWebPage" - rm -f "${SHARED_WEB_DIR}/$(echo "$theWebPage" | cut -f1 -d'.').title" - fi - _Mount_WebUI_ - else - Say "${REDct}**ERROR**${NOct}: Unable to download latest WebUI ASP file for $SCRIPT_NAME." - fi - else - _Mount_WebUI_ - fi - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-11] ## -##----------------------------------------## -_Unmount_WebUI_() -{ - if [ ! -f "$SCRIPT_WEB_ASP_PATH" ] - then - Say "${CRITct}**ERROR**${NOct}: The WebUI page file for $SCRIPT_NAME is NOT found." - return 1 - fi - local webPageFile - - Say "Unmounting WebUI page for $SCRIPT_NAME" - - eval exec "$WEBUI_LOCKFD>$WEBUI_LOCKFILE" - flock -x "$WEBUI_LOCKFD" - - webPageFile="$(_GetWebUIPage_ "$SCRIPT_WEB_ASP_PATH")" - if [ -z "$webPageFile" ] || [ "$webPageFile" = "NONE" ] - then - Say "WebUI page file for $SCRIPT_NAME is NOT found to uninstall." - flock -u "$WEBUI_LOCKFD" - return 1 - fi - - if [ -f "$TEMP_MENU_TREE" ] - then - sed -i "/url: \"$webPageFile\", tabName: \"$SCRIPT_NAME\"/d" "$TEMP_MENU_TREE" - fi - rm -f "${SHARED_WEB_DIR}/$webPageFile" - rm -f "${SHARED_WEB_DIR}/$(echo "$webPageFile" | cut -f1 -d'.').title" - - umount "$ORIG_MENU_TREE" 2>/dev/null - mount -o bind "$TEMP_MENU_TREE" "$ORIG_MENU_TREE" - flock -u "$WEBUI_LOCKFD" - - Say "${GRNct}$SCRIPT_NAME WebUI page unmounted successfully." - /sbin/service restart_httpd >/dev/null 2>&1 & - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-12] ## -##----------------------------------------## -_AutoStartupHook_() -{ - local theScriptNameTag="#${SCRIPT_NAME}#" - local theHookScriptFile="${SCRIPTS_PATH}/services-start" - local theScriptFilePath="${SCRIPTS_PATH}/${SCRIPT_NAME}.sh" - - case "$1" in - create) - if [ -f "$theHookScriptFile" ] - then - theLineCount="$(grep -c "$theScriptNameTag" "$theHookScriptFile")" - theLineCountEx="$(grep -cx '\[ -x '"$theScriptFilePath"' \] && '"$theScriptFilePath"' startup "$@" & '"$theScriptNameTag" "$theHookScriptFile")" - - if [ "$theLineCount" -gt 1 ] || { [ "$theLineCountEx" -eq 0 ] && [ "$theLineCount" -gt 0 ] ; } - then - sed -i "/${theScriptNameTag}/d" "$theHookScriptFile" - fi - if [ "$theLineCountEx" -eq 0 ] - then - { - echo '[ -x '"$theScriptFilePath"' ] && '"$theScriptFilePath"' startup "$@" & '"$theScriptNameTag" - } >> "$theHookScriptFile" - fi - else - { - echo "#!/bin/sh" ; echo - echo '[ -x '"$theScriptFilePath"' ] && '"$theScriptFilePath"' startup "$@" & '"$theScriptNameTag" - echo - } > "$theHookScriptFile" - fi - chmod 755 "$theHookScriptFile" - ;; - delete) - if [ -f "$theHookScriptFile" ] && \ - { grep -q "$theScriptNameTag" "$theHookScriptFile" || \ - grep -q "$theScriptFilePath" "$theHookScriptFile" ; } - then - theFixedPath="$(echo "$theScriptFilePath" | sed 's/[\/.]/\\&/g')" - sed -i "/${theScriptNameTag}/d" "$theHookScriptFile" - sed -i "/$theFixedPath startup/d" "$theHookScriptFile" - fi - ;; - esac -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-12] ## -##----------------------------------------## -_AutoServiceEvent_() -{ - local theScriptNameTag="#${SCRIPT_NAME}#" - local theHookScriptFile="${SCRIPTS_PATH}/service-event" - local theScriptFilePath="${SCRIPTS_PATH}/${SCRIPT_NAME}.sh" - - case "$1" in - create) - if [ -f "$theHookScriptFile" ] - then - theLineCount="$(grep -c "$theScriptNameTag" "$theHookScriptFile")" - theLineCountEx="$(grep -cx 'if echo "$2" | /bin/grep -q "'"$SCRIPT_NAME"'" ; then { '"$theScriptFilePath"' service_event "$@" & }; fi '"$theScriptNameTag" "$theHookScriptFile")" - - if [ "$theLineCount" -gt 1 ] || { [ "$theLineCountEx" -eq 0 ] && [ "$theLineCount" -gt 0 ]; } - then - sed -i "/${theScriptNameTag}/d" "$theHookScriptFile" - fi - if [ "$theLineCountEx" -eq 0 ] - then - { - echo 'if echo "$2" | /bin/grep -q "'"$SCRIPT_NAME"'" ; then { '"$theScriptFilePath"' service_event "$@" & }; fi '"$theScriptNameTag" - } >> "$theHookScriptFile" - fi - else - { - echo "#!/bin/sh" ; echo - echo 'if echo "$2" | /bin/grep -q "'"$SCRIPT_NAME"'" ; then { '"$theScriptFilePath"' service_event "$@" & }; fi '"$theScriptNameTag" - echo - } > "$theHookScriptFile" - fi - chmod 755 "$theHookScriptFile" - ;; - delete) - if [ -f "$theHookScriptFile" ] && \ - { grep -q "$theScriptNameTag" "$theHookScriptFile" || \ - grep -q "$theScriptFilePath" "$theHookScriptFile" ; } - then - theFixedPath="$(echo "$theScriptFilePath" | sed 's/[\/.]/\\&/g')" - sed -i "/${theScriptNameTag}/d" "$theHookScriptFile" - sed -i "/$theFixedPath service_event/d" "$theHookScriptFile" - fi - ;; - esac -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-05] ## -##----------------------------------------## -_SetVersionSharedSettings_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] || \ - ! echo "$1" | grep -qE "^(local|server|delete)$" - then return 1; fi - - if [ "$1" = "delete" ] - then - if [ -f "$SHARED_SETTINGS_FILE" ] - then - if grep -q "^MerlinAU_version_" "$SHARED_SETTINGS_FILE" - then - sed -i "/^MerlinAU_version_local/d" "$SHARED_SETTINGS_FILE" - sed -i "/^MerlinAU_version_server/d" "$SHARED_SETTINGS_FILE" - fi - fi - return 0 - fi - if [ $# -lt 2 ] || [ -z "$2" ] ; then return 1; fi - - local versionTypeStr="" - [ "$1" = "local" ] && versionTypeStr="MerlinAU_version_local" - [ "$1" = "server" ] && versionTypeStr="MerlinAU_version_server" - - if [ -f "$SHARED_SETTINGS_FILE" ] - then - if grep -q "^${versionTypeStr}.*" "$SHARED_SETTINGS_FILE" - then - if [ "$2" != "$(grep "^$versionTypeStr" "$SHARED_SETTINGS_FILE" | cut -f2 -d' ')" ] - then - sed -i "s/^${versionTypeStr}.*/$versionTypeStr $2/" "$SHARED_SETTINGS_FILE" - fi - else - echo "$versionTypeStr $2" >> "$SHARED_SETTINGS_FILE" - fi - else - echo "$versionTypeStr $2" > "$SHARED_SETTINGS_FILE" - fi - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-20] ## -##----------------------------------------## -_CreateDirPaths_() -{ - if [ ! -d "$SETTINGS_DIR" ] - then - mkdir -p "$SETTINGS_DIR" - chmod 755 "$SETTINGS_DIR" - fi - ! "$mountWebGUI_OK" && return 0 - - if [ ! -d "$SCRIPT_WEB_DIR" ] - then - mkdir -p "$SCRIPT_WEB_DIR" - chmod 775 "$SCRIPT_WEB_DIR" - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-07] ## -##----------------------------------------## -_CreateSymLinks_() -{ - if [ -d "$SCRIPT_WEB_DIR" ] - then - rm -rf "${SCRIPT_WEB_DIR:?}/"* 2>/dev/null - fi - ! "$mountWebGUI_OK" && return 0 - - ln -sf "$CONFIG_FILE" "${SCRIPT_WEB_DIR}/config.htm" 2>/dev/null - ln -sf "$HELPER_JSFILE" "${SCRIPT_WEB_DIR}/checkHelper.js" 2>/dev/null - ln -sf "$PSWD_CHECK_JS" "${SCRIPT_WEB_DIR}/pswdCheckStatus.js" 2>/dev/null - ln -sf "$CHANGELOG_PATH" "${SCRIPT_WEB_DIR}/changelog.htm" 2>/dev/null -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-07] ## -##----------------------------------------## -_WriteVarDefToHelperJSFile_() -{ - if [ $# -lt 2 ] || [ -z "$1" ] || [ -z "$2" ] - then return 1; fi - - local varValue fixedVal - if [ $# -eq 3 ] && [ "$3" = "true" ] - then varValue="$2" - else varValue="'${2}'" - fi - - if [ ! -s "$HELPER_JSFILE" ] - then - echo "var $1 = ${varValue};" > "$HELPER_JSFILE" - elif ! grep -q "^var $1 =.*" "$HELPER_JSFILE" - then - echo "var $1 = ${varValue};" >> "$HELPER_JSFILE" - elif ! grep -q "^var $1 = ${varValue};" "$HELPER_JSFILE" - then - fixedVal="$(echo "$varValue" | sed 's/[\/&]/\\&/g')" - sed -i "s/^var $1 =.*/var $1 = ${fixedVal};/" "$HELPER_JSFILE" - fi -} - -##-------------------------------------## -## Added by Martinski W. [2025-Jan-20] ## -##-------------------------------------## -_WebUI_AutoFWUpdateCheckCronSchedule_() -{ - ! "$mountWebGUI_OK" && return 0 - local fwUpdtCronScheduleRaw fwUpdtCronScheduleStr - fwUpdtCronScheduleRaw="$(Get_Custom_Setting FW_New_Update_Cron_Job_Schedule)" - fwUpdtCronScheduleStr="$(_TranslateCronSchedHR_ "$fwUpdtCronScheduleRaw")" - _WriteVarDefToHelperJSFile_ "fwAutoUpdateCheckCronSchedHR" "$fwUpdtCronScheduleStr" -} - -##-------------------------------------## -## Added by Martinski W. [2025-Jan-20] ## -##-------------------------------------## -_WebUI_AutoScriptUpdateCronSchedule_() -{ - ! "$mountWebGUI_OK" && return 0 - local scriptUpdtCronSchedRaw scriptUpdtCronSchedStr - scriptUpdtCronSchedRaw="$(_GetScriptAutoUpdateCronSchedule_)" - scriptUpdtCronSchedStr="$(_TranslateCronSchedHR_ "$scriptUpdtCronSchedRaw")" - _WriteVarDefToHelperJSFile_ "scriptAutoUpdateCronSchedHR" "$scriptUpdtCronSchedStr" -} - -##-------------------------------------## -## Added by Martinski W. [2025-Jan-27] ## -##-------------------------------------## -_WebUI_SetEmailConfigFileFromAMTM_() -{ - ! "$mountWebGUI_OK" && return 0 - _CheckEMailConfigFileFromAMTM_ 0 - _WriteVarDefToHelperJSFile_ "isEMailConfigEnabledInAMTM" "$isEMailConfigEnabledInAMTM" true -} - -##-------------------------------------## -## Added by Martinski W. [2025-Jan-15] ## -##-------------------------------------## -_ActionsAfterNewConfigSettings_() -{ - if [ ! -s "${CONFIG_FILE}.bak" ] || \ - diff -q "$CONFIG_FILE" "${CONFIG_FILE}.bak" >/dev/null 2>&1 - then return 1 ; fi - - _ConfigOptionChanged_() - { - if diff "$CONFIG_FILE" "${CONFIG_FILE}.bak" | grep -q "$1" - then return 0 - else return 1 - fi - } - local ccNewEmailAddr ccNewEmailName newScriptAUpdateVal - - if _ConfigOptionChanged_ "FW_New_Update_EMail_CC_Address=" - then - ccNewEmailAddr="$(Get_Custom_Setting FW_New_Update_EMail_CC_Address)" - ccNewEmailName="${ccNewEmailAddr%%@*}" - Update_Custom_Settings FW_New_Update_EMail_CC_Name "$ccNewEmailName" - fi - if _ConfigOptionChanged_ "FW_New_Update_Postponement_Days=" - then - _Calculate_NextRunTime_ - fi - if _ConfigOptionChanged_ "Allow_Script_Auto_Update" - then - ScriptAutoUpdateSetting="$(Get_Custom_Setting Allow_Script_Auto_Update)" - if [ "$ScriptAutoUpdateSetting" = "DISABLED" ] - then - _DelScriptAutoUpdateHook_ - _DelScriptAutoUpdateCronJob_ - elif [ "$ScriptAutoUpdateSetting" = "ENABLED" ] - then - scriptUpdateCronSched="$(_GetScriptAutoUpdateCronSchedule_)" - if _ValidateCronJobSchedule_ "$scriptUpdateCronSched" - then - _AddScriptAutoUpdateCronJob_ && _AddScriptAutoUpdateHook_ - fi - fi - fi - if _ConfigOptionChanged_ "CheckChangeLog" - then - currentChangelogValue="$(Get_Custom_Setting CheckChangeLog)" - if [ "$currentChangelogValue" = "DISABLED" ] - then - Delete_Custom_Settings "FW_New_Update_Changelog_Approval" - elif [ "$currentChangelogValue" = "ENABLED" ] - then - Update_Custom_Settings FW_New_Update_Changelog_Approval TBD - fi - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-07] ## -##----------------------------------------## -_UpdateConfigFromWebUISettings_() -{ - [ ! -f "$SHARED_SETTINGS_FILE" ] && return 1 - - local settingsMergeOK=true logMsgTag="with errors." - local oldLoginCredsENC doRouterLoginTest=false - - # Check for 'MerlinAU_' entries excluding 'version' # - if [ "$(grep "^MerlinAU_" "$SHARED_SETTINGS_FILE" | grep -vc "_version")" -gt 0 ] - then - Say "Updated settings from WebUI found, merging into $CONFIG_FILE" - cp -a "$CONFIG_FILE" "${CONFIG_FILE}.bak" - - # Extract 'MerlinAU_' entries excluding 'version' # - grep "^MerlinAU_" "$SHARED_SETTINGS_FILE" | grep -v "_version" > "$TEMPFILE" - sed -i 's/^MerlinAU_//g;s/ /=/g' "$TEMPFILE" - - while IFS='' read -r line || [ -n "$line" ] - do - keySettingName="$(echo "$line" | cut -f1 -d'=')" - keySettingValue="$(echo "$line" | cut -f2- -d'=')" - - if [ "$keySettingName" = "FW_New_Update_ZIP_Directory_Path" ] - then - if _Validate_FW_UpdateZIP_DirectoryPath_ "$keySettingValue" true - then - Say "Directory path [$keySettingValue] was updated successfully." - else - settingsMergeOK=false - Say "**ERROR**: Could NOT update directory path [$keySettingValue]" - fi - continue - elif [ "$keySettingName" = "FW_New_Update_LOG_Directory_Path" ] - then - if _Validate_FW_UpdateLOG_DirectoryPath_ "$keySettingValue" true - then - Say "Directory path [$keySettingValue] was updated successfully." - else - settingsMergeOK=false - Say "**ERROR**: Could NOT update directory path [$keySettingValue]" - fi - continue - fi - if [ "$keySettingName" = "FW_New_Update_Cron_Job_Schedule" ] - then # Replace delimiter char placed by the WebGUI # - keySettingValue="$(echo "$keySettingValue" | sed 's/|/ /g')" - fi - if [ "$keySettingName" = "credentials_base64" ] - then - oldLoginCredsENC="$(Get_Custom_Setting credentials_base64)" - if [ "$oldLoginCredsENC" = "$keySettingValue" ] - then _UpdateLoginPswdCheckHelper_ OldPSWD - else _UpdateLoginPswdCheckHelper_ NewPSWD - fi - doRouterLoginTest="$runLoginCredentialsTest" - fi - Update_Custom_Settings "$keySettingName" "$keySettingValue" - done < "$TEMPFILE" - - # Extract 'MerlinAU_version_*' separately (if found) # - grep '^MerlinAU_version_.*' "$SHARED_SETTINGS_FILE" > "$TEMPFILE" - # Now remove all 'MerlinAU_*' entries # - sed -i "/^MerlinAU_.*/d" "$SHARED_SETTINGS_FILE" - - # Reconstruct the shared settings file # - mv -f "$SHARED_SETTINGS_FILE" "${SHARED_SETTINGS_FILE}.bak" - cat "${SHARED_SETTINGS_FILE}.bak" "$TEMPFILE" > "$SHARED_SETTINGS_FILE" - rm -f "$TEMPFILE" "${SHARED_SETTINGS_FILE}.bak" - - _ActionsAfterNewConfigSettings_ - - "$settingsMergeOK" && logMsgTag="successfully." - Say "Merge of updated settings from WebUI was completed ${logMsgTag}" - - if ! "$settingsMergeOK" - then ## Reset for Next Check ## - { sleep 15 ; _UpdateHelperJSFile_ "$extCheckALLvarID" "true" ; } & - fi - - ## Do this ONLY IF requested by user ## - "$doRouterLoginTest" && _TestLoginCredentials_ - else - Say "No updated settings from WebUI found. No merge into $CONFIG_FILE necessary." - fi - return 0 -} - -##-------------------------------------## -## Added by Martinski W. [2024-Dec-31] ## -##-------------------------------------## -newGUIversionNum="$(_ScriptVersionStrToNum_ '1.4.0')" -# Temporary code used to migrate to future new script version # -_CheckForNewGUIVersionUpdate_() -{ - local retCode theScriptVerNum urlScriptVerNum - if [ $# -lt 2 ] || [ -z "$1" ] || [ -z "$2" ] - then - theScriptVerNum="$ScriptVersionNum" - urlScriptVerNum="$DLRepoVersionNum" - else - theScriptVerNum="$(_ScriptVersionStrToNum_ "$1")" - urlScriptVerNum="$(_ScriptVersionStrToNum_ "$2")" - fi - if [ "$theScriptVerNum" -lt "$newGUIversionNum" ] && \ - [ "$urlScriptVerNum" -ge "$newGUIversionNum" ] - then retCode=0 - else retCode=1 - fi - return "$retCode" -} - -##-------------------------------------## -## Added by Martinski W. [2025-Mar-24] ## -##-------------------------------------## -_GetDLScriptVersion_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] || [ ! -s "$1" ] - then echo ; return 1 ; fi - - local DLversBuildNum=0 - if [ "$(wc -l < "$1")" -eq 2 ] - then - DLversBuildNum="$(tail -n1 "$1")" - [ -z "$DLversBuildNum" ] && DLversBuildNum=0 - fi - echo "$(head -n1 "$1")|$DLversBuildNum" - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Feb-15] ## -##----------------------------------------## -_CurlFileDownload_() -{ - if [ $# -lt 2 ] || [ -z "$1" ] || [ -z "$2" ] - then return 1 ; fi - local retCode=1 - local tempFilePathDL="${2}.DL.TMP" - local srceFilePathDL="${SCRIPT_URL_REPO}/$1" - - curl -LSs --retry 4 --retry-delay 5 --retry-connrefused \ - "$srceFilePathDL" -o "$tempFilePathDL" - if [ $? -ne 0 ] || [ ! -s "$tempFilePathDL" ] || \ - grep -iq "^404: Not Found" "$tempFilePathDL" - then - rm -f "$tempFilePathDL" - retCode=1 - else - if [ "$1" = "$SCRIPT_WEB_ASP_FILE" ] && \ - [ -f "$2" ] && [ -f "$TEMP_MENU_TREE" ] && \ - ! diff -q "$tempFilePathDL" "$2" >/dev/null 2>&1 - then updatedWebUIPage=true - else updatedWebUIPage=false - fi - mv -f "$tempFilePathDL" "$2" - retCode=0 - fi - - return "$retCode" -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-27] ## -##----------------------------------------## -_DownloadScriptFiles_() -{ - local retCode isUpdateAction updatedWebUIPage theWebPage - - if [ $# -gt 0 ] && [ "$1" = "update" ] - then isUpdateAction=true - else isUpdateAction=false - fi - updatedWebUIPage=false - - if _CurlFileDownload_ "version.txt" "$SCRIPT_VERPATH" - then - retCode=0 ; chmod 664 "$SCRIPT_VERPATH" - else - retCode=1 - Say "${REDct}**ERROR**${NOct}: Unable to download latest version file for $SCRIPT_NAME." - fi - if "$mountWebGUI_OK" && \ - _CurlFileDownload_ "$SCRIPT_WEB_ASP_FILE" "$SCRIPT_WEB_ASP_PATH" - then - chmod 664 "$SCRIPT_WEB_ASP_PATH" - if "$updatedWebUIPage" - then - theWebPage="$(_GetWebUIPage_ "$SCRIPT_WEB_ASP_PATH")" - if [ -n "$theWebPage" ] && [ "$theWebPage" != "NONE" ] - then - sed -i "/url: \"$theWebPage\", tabName: \"$SCRIPT_NAME\"/d" "$TEMP_MENU_TREE" - rm -f "${SHARED_WEB_DIR}/$theWebPage" - rm -f "${SHARED_WEB_DIR}/$(echo "$theWebPage" | cut -f1 -d'.').title" - fi - "$isUpdateAction" && _Mount_WebUI_ - fi - retCode=0 - elif "$mountWebGUI_OK" - then - retCode=1 - Say "${REDct}**ERROR**${NOct}: Unable to download latest WebUI ASP file for $SCRIPT_NAME." - fi - if _CurlFileDownload_ "${SCRIPT_NAME}.sh" "$ScriptFilePath" - then - retCode=0 ; chmod 755 "$ScriptFilePath" - else - retCode=1 - Say "${REDct}**ERROR**${NOct}: Unable to download latest script file for $SCRIPT_NAME." - fi - return "$retCode" -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-24] ## -##----------------------------------------## -_SCRIPT_UPDATE_() -{ - local extraParam="" - - if [ $# -gt 0 ] && [ "$1" = "force" ] - then - printf "\n${CYANct}Force downloading latest script version...${NOct}\n" - _CheckForNewScriptUpdates_ -quietcheck - if _CheckForNewGUIVersionUpdate_ "$SCRIPT_VERSION" "$DLRepoVersion" - then extraParam="install" - fi - printf "${CYANct}Downloading latest version [$DLRepoVersion] of ${SCRIPT_NAME}${NOct}\n" - - if _DownloadScriptFiles_ update - then - printf "${CYANct}$SCRIPT_NAME files were successfully updated.${NOct}\n\n" - if "$mountWebGUI_OK" - then - _SetVersionSharedSettings_ local "$DLRepoVersion" - _SetVersionSharedSettings_ server "$DLRepoVersion" - fi - sleep 1 - _ReleaseLock_ - exec "$ScriptFilePath" $extraParam - exit 0 - fi - return 0 - fi - - ! _CheckForNewScriptUpdates_ && return 1 - - clear - _ShowLogo_ - - printf "\n${YLWct}Script Update Utility${NOct}\n\n" - printf "${CYANct}Version Currently Installed: ${YLWct}${SCRIPT_VERSION}${NOct}\n" - printf "${CYANct}Update Version Available Now: ${YLWct}${DLRepoVersion}${NOct}\n\n" - - if "$mountWebGUI_OK" - then _SetVersionSharedSettings_ server "$DLRepoVersion" ; fi - - if [ "$SCRIPT_VERSION" = "$DLRepoVersion" ] - then - echo -e "${CYANct}You are on the latest version! Would you like to download anyways?${NOct}" - echo -e "${CYANct}This will overwrite your currently installed version.${NOct}" - if _WaitForYESorNO_ - then - printf "\n\n${CYANct}Downloading $SCRIPT_NAME $DLRepoVersion version.${NOct}\n" - - if _DownloadScriptFiles_ update - then - if "$mountWebGUI_OK" - then _SetVersionSharedSettings_ local "$DLRepoVersion" - fi - printf "\n${CYANct}Download successful!${NOct}\n" - printf "$(date) - Successfully downloaded $SCRIPT_NAME v${DLRepoVersion}\n" - fi - _WaitForEnterKey_ - return - else - printf "\n\n${GRNct}Exiting Script Update Utility...${NOct}\n" - sleep 1 - return - fi - elif [ "$scriptUpdateNotify" != "0" ] - then - echo -e "${CYANct}Bingo! New version available! Would you like to update now?${NOct}" - if _WaitForYESorNO_ - then - printf "\n\n${CYANct}Downloading $SCRIPT_NAME $DLRepoVersion version.${NOct}\n" - - if _DownloadScriptFiles_ update - then - if "$mountWebGUI_OK" - then _SetVersionSharedSettings_ local "$DLRepoVersion" - fi - printf "\n$(date) - Successfully downloaded $SCRIPT_NAME v${DLRepoVersion}\n" - printf "${CYANct}Update successful! Restarting script...${NOct}\n" - sleep 1 - _CheckForNewGUIVersionUpdate_ && extraParam="install" - _ReleaseLock_ - exec "$ScriptFilePath" $extraParam - exit 0 - else - _WaitForEnterKey_ - return - fi - else - printf "\n\n${GRNct}Exiting Script Update Utility...${NOct}\n" - sleep 1 - return - fi - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-24] ## -##----------------------------------------## -_CheckForNewScriptUpdates_() -{ - local verStr DLScriptVerPath="${SCRIPT_VERPATH}.DL.tmp" - echo - DLRepoVersion="$SCRIPT_VERSION" - if [ -s "$SCRIPT_VERPATH" ] - then - if verStr="$(_GetDLScriptVersion_ "$SCRIPT_VERPATH")" - then - DLRepoVersion="$(echo "$verStr" | awk -F '|' '{print $1}')" - DLRepoBuildNum="$(echo "$verStr" | awk -F '|' '{print $2}')" - ScriptBuildNum="$DLRepoBuildNum" - fi - fi - - if ! _CurlFileDownload_ "version.txt" "$DLScriptVerPath" - then - Say "${REDct}**ERROR**${NOct}: Unable to download latest version file for $SCRIPT_NAME." - scriptUpdateNotify=0 - return 1 - fi - - if verStr="$(_GetDLScriptVersion_ "$DLScriptVerPath")" - then - DLRepoVersion="$(echo "$verStr" | awk -F '|' '{print $1}')" - DLRepoBuildNum="$(echo "$verStr" | awk -F '|' '{print $2}')" - fi - rm -f "$DLScriptVerPath" - - if [ -z "$DLRepoVersion" ] - then - Say "${REDct}**ERROR**${NOct}: Variable for downloaded version is empty." - scriptUpdateNotify=0 - return 1 - fi - - DLRepoVersionNum="$(_ScriptVersionStrToNum_ "$DLRepoVersion")" - ScriptVersionNum="$(_ScriptVersionStrToNum_ "$SCRIPT_VERSION")" - - if [ "$DLRepoVersionNum" -gt "$ScriptVersionNum" ] || \ - { - [ "$DLRepoBuildNum" -gt "$ScriptBuildNum" ] && \ - [ "$DLRepoVersionNum" -eq "$ScriptVersionNum" ] - } - then - scriptUpdateNotify="New script update available. -${REDct}v${SCRIPT_VERSION}${NOct} --> ${GRNct}v${DLRepoVersion}${NOct}" - - if [ $# -gt 0 ] && [ "$1" = "-quietcheck" ] - then return 0 - fi - Say "$myLAN_HostName - A new script version update (v$DLRepoVersion) is available to download." - if [ "$ScriptAutoUpdateSetting" = "ENABLED" ] - then - _SCRIPT_UPDATE_ force - fi - else - scriptUpdateNotify=0 - fi - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2023-Nov-22] ## -##----------------------------------------## -_GetLatestFWUpdateVersionFromRouter_() -{ - local retCode=0 webState newVersionStr - - webState="$(nvram get webs_state_flag)" - if [ -z "$webState" ] || [ "$webState" -eq 0 ] - then retCode=1 ; fi - - newVersionStr="$(nvram get webs_state_info | sed 's/_/./g')" - if [ $# -eq 0 ] || [ -z "$1" ] - then - newVersionStr="$(echo "$newVersionStr" | awk -F '-' '{print $1}')" - fi - - [ -z "$newVersionStr" ] && retCode=1 - echo "$newVersionStr" ; return "$retCode" -} - -##------------------------------------------## -## Modified by ExtremeFiretop [2024-Dec-28] ## -##------------------------------------------## -_CreateEMailContent_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi - local fwInstalledVersion fwNewUpdateVersion - local savedInstalledVersion savedNewUpdateVersion - local subjectStr emailBodyTitle="" release_version - - rm -f "$tempEMailContent" "$tempEMailBodyMsg" - - if [ -s "$tempNodeEMailList" ] - then subjectStr="F/W Update Status for $node_lan_hostname" - else subjectStr="F/W Update Status for $MODEL_ID" - fi - fwInstalledVersion="$(_GetCurrentFWInstalledLongVersion_)" - if ! "$offlineUpdateTrigger" - then - fwNewUpdateVersion="$(_GetLatestFWUpdateVersionFromRouter_)" - else - fwNewUpdateVersion="$(Get_Custom_Setting "FW_New_Update_Notification_Vers")" - fi - - # Remove "_rog" or "_tuf" or -gHASHVALUES or -Gnuton* suffix to avoid version comparison failure, can't remove all for proper beta and alpha comparison # - fwInstalledVersion="$(echo "$fwInstalledVersion" | sed -E 's/(_(rog|tuf)|-g[0-9a-f]{10}|-gnuton[0-9]+)$//')" - - case "$1" in - FW_UPDATE_TEST_EMAIL) - emailBodyTitle="Testing Email Notification" - { - echo "This is a TEST of the F/W Update email notification from the ${MODEL_ID} router." - printf "\nThe F/W version that is currently installed:\n${fwInstalledVersion}\n" - } > "$tempEMailBodyMsg" - ;; - NEW_FW_UPDATE_STATUS) - emailBodyTitle="New Firmware Update for ASUS Router" - { - echo "A new F/W Update version ${fwNewUpdateVersion} is available for the ${MODEL_ID} router." - printf "\nThe F/W version that is currently installed:\n${fwInstalledVersion}\n" - printf "\nNumber of days to postpone flashing the new F/W Update version: ${FW_UpdatePostponementDays}\n" - printf "\nPlease click here to review the changelog:\n" - if "$isGNUtonFW" - then - printf "${GnutonChangeLogURL}\n" - else - printf "${MerlinChangeLogURL}\n" - fi - [ "$FW_UpdateExpectedRunDate" != "TBD" ] && \ - printf "\nThe firmware update is expected to occur on: ${FW_UpdateExpectedRunDate}\n" - } > "$tempEMailBodyMsg" - ;; - AGGREGATED_UPDATE_NOTIFICATION) - if "$aiMeshNodes_OK" && [ -n "$node_list" ]; then - nodefwNewUpdateVersion="$(_GetLatestFWUpdateVersionFromNode_ 1)" - fi - if [ -z "$nodefwNewUpdateVersion" ] - then - Say "${REDct}**ERROR**${NOct}: Unable to send node email notification [No saved info]." - return 1 - fi - emailBodyTitle="New Firmware Update(s) for AiMesh Node(s)" - NODE_UPDATE_CONTENT="$(cat "$tempNodeEMailList")" - { - echo "The following AiMesh Node(s) have a new F/W Update version available:" - echo "$NODE_UPDATE_CONTENT" - } > "$tempEMailBodyMsg" - ;; - START_FW_UPDATE_STATUS) - emailBodyTitle="New Firmware Flash Started" - { - echo "Started flashing the new F/W Update version ${fwNewUpdateVersion} on the ${MODEL_ID} router." - printf "\nThe F/W version that is currently installed:\n${fwInstalledVersion}\n" - } > "$tempEMailBodyMsg" - ;; - STOP_FW_UPDATE_APPROVAL) - emailBodyTitle="WARNING" - if "$isEMailFormatHTML" - then - # Highlight high-risk terms using HTML with a yellow background # - highlighted_changelog_contents="$(echo "$changelog_contents" | sed -E "s/($high_risk_terms)/\1<\/span>/gi")" - else - # Step 1: Enclose matched terms with unique markers that don't conflict with '>' and '<' - highlighted_changelog_contents="$(echo "$changelog_contents" | sed -E "s/($high_risk_terms)/\[\[UPPER\]\]\1\[\[ENDUPPER\]\]/gi")" - - # Step 2: Modify the awk script with correct marker lengths - highlighted_changelog_contents="$(echo "$highlighted_changelog_contents" | awk ' - BEGIN { - upper_marker = "[[UPPER]]" - endupper_marker = "[[ENDUPPER]]" - upper_marker_length = length(upper_marker) - endupper_marker_length = length(endupper_marker) - } - { - while (match($0, /\[\[UPPER\]\][^\[]*\[\[ENDUPPER\]\]/)) { - prefix = substr($0, 1, RSTART - 1) - match_text_start = RSTART + upper_marker_length - match_text_length = RLENGTH - upper_marker_length - endupper_marker_length - match_text = substr($0, match_text_start, match_text_length) - suffix = substr($0, RSTART + RLENGTH) - match_text_upper = toupper(match_text) - $0 = prefix ">" match_text_upper "<" suffix - } - print - } - ')" - fi - { - echo "Found high-risk phrases in the changelog file while Auto-Updating to version ${fwNewUpdateVersion} on the ${MODEL_ID} router." - echo "Changelog contents include the following changes:" - echo "$highlighted_changelog_contents" - printf "\nPlease run script interactively to approve this F/W Update from current version:\n${fwInstalledVersion}\n" - } > "$tempEMailBodyMsg" - ;; - NEW_BM_BACKUP_FAILED) - emailBodyTitle="WARNING" - { - echo "Backup failed during the F/W Update process to version ${fwNewUpdateVersion} on the ${MODEL_ID} router." - echo "Flashing the F/W Update on the ${MODEL_ID} router is now cancelled." - printf "\nPlease check backupmon.sh configuration and retry F/W Update from current version:\n${fwInstalledVersion}\n" - } > "$tempEMailBodyMsg" - ;; - FAILED_FW_UNZIP_STATUS) - emailBodyTitle="**ERROR**" - { - echo "Unable to decompress the F/W Update ZIP file for version ${fwNewUpdateVersion} on the ${MODEL_ID} router." - echo "Flashing the F/W Update on the ${MODEL_ID} router is now cancelled due to decompress error." - printf "\nPlease retry F/W Update from current version:\n${fwInstalledVersion}\n" - } > "$tempEMailBodyMsg" - ;; - FAILED_FW_CHECKSUM_STATUS) - emailBodyTitle="**ERROR**" - { - echo "Checksum verification failed during the F/W Update process to version ${fwNewUpdateVersion} on the ${MODEL_ID} router." - echo "Flashing the F/W Update on the ${MODEL_ID} router is now cancelled due to checksum mismatch." - printf "\nPlease retry F/W Update from current version:\n${fwInstalledVersion}\n" - } > "$tempEMailBodyMsg" - ;; - FAILED_FW_UPDATE_STATUS) - emailBodyTitle="**ERROR**" - { - echo "Flashing of new F/W Update version ${fwNewUpdateVersion} for the ${MODEL_ID} router failed." - printf "\nThe F/W version that is currently installed:\n${fwInstalledVersion}\n" - } > "$tempEMailBodyMsg" - ;; - POST_REBOOT_FW_UPDATE_SETUP) - { - echo "FW_InstalledVersion=$fwInstalledVersion" - echo "FW_NewUpdateVersion=$fwNewUpdateVersion" - } > "$saveEMailInfoMsg" - _AddPostUpdateEmailNotifyScriptHook_ - return 0 - ;; - POST_REBOOT_FW_UPDATE_STATUS) - if [ ! -f "$saveEMailInfoMsg" ] - then - Say "${REDct}**ERROR**${NOct}: Unable to send post-update email notification [No saved info file]." - return 1 - fi - savedInstalledVersion="$(grep "^FW_InstalledVersion=" "$saveEMailInfoMsg" | awk -F '=' '{print $2}')" - savedNewUpdateVersion="$(grep "^FW_NewUpdateVersion=" "$saveEMailInfoMsg" | awk -F '=' '{print $2}')" - if [ -z "$savedInstalledVersion" ] || [ -z "$savedNewUpdateVersion" ] - then - Say "${REDct}**ERROR**${NOct}: Unable to send post-update email notification [Saved info is empty]." - return 1 - fi - if [ "$savedNewUpdateVersion" = "$fwInstalledVersion" ] - then - emailBodyTitle="Successful Firmware Update" - { - echo "Flashing of new F/W Update version ${fwInstalledVersion} for the ${MODEL_ID} router was successful." - printf "\nThe F/W version that was previously installed:\n${savedInstalledVersion}\n" - } > "$tempEMailBodyMsg" - else - emailBodyTitle="**ERROR**" - { - echo "Flashing of new F/W Update version ${savedNewUpdateVersion} for the ${MODEL_ID} router failed." - printf "\nThe F/W version that is currently installed:\n${fwInstalledVersion}\n" - } > "$tempEMailBodyMsg" - fi - rm -f "$saveEMailInfoMsg" - ;; - *) return 1 - ;; - esac - - ! "$isEMailFormatHTML" && sed -i 's/[<]b[>]//g ; s/[<]\/b[>]//g' "$tempEMailBodyMsg" - - if [ -n "$CC_NAME" ] && [ -n "$CC_ADDRESS" ] - then - CC_ADDRESS_ARG="--mail-rcpt $CC_ADDRESS" - CC_ADDRESS_STR="\"${CC_NAME}\" <$CC_ADDRESS>" - fi - - ## Header-1 ## - cat < "$tempEMailContent" -From: "$FROM_NAME" <$FROM_ADDRESS> -To: "$TO_NAME" <$TO_ADDRESS> -EOF - - [ -n "$CC_ADDRESS_STR" ] && \ - printf "Cc: %s\n" "$CC_ADDRESS_STR" >> "$tempEMailContent" - - ## Header-2 ## - cat <> "$tempEMailContent" -Subject: $subjectStr -Date: $(date -R) -EOF - - if "$isEMailFormatHTML" - then - cat <> "$tempEMailContent" -MIME-Version: 1.0 -Content-Type: text/html; charset="UTF-8" -Content-Disposition: inline - - - -

${emailBodyTitle}

-
-EOF
-    else
-        cat <> "$tempEMailContent"
-Content-Type: text/plain; charset="UTF-8"
-Content-Transfer-Encoding: quoted-printable
-Content-Disposition: inline
-
-EOF
-       [ -n "$emailBodyTitle" ] && \
-       printf "%s\n\n" "$emailBodyTitle" >> "$tempEMailContent"
-   fi
-
-   ## Body ##
-   cat "$tempEMailBodyMsg" >> "$tempEMailContent"
-
-   ## Footer ##
-   if "$isEMailFormatHTML"
-   then
-       cat <> "$tempEMailContent"
-
-Sent by the "${ScriptFNameTag}" utility.
-From the "${FRIENDLY_ROUTER_NAME}" router.
-
-$(date +"$theEMailDateTimeFormat")
-
-EOF - else - cat <> "$tempEMailContent" - -Sent by the "${ScriptFNameTag}" utility. -From the "${FRIENDLY_ROUTER_NAME}" router. - -$(date +"$theEMailDateTimeFormat") -EOF - fi - - rm -f "$tempEMailBodyMsg" - rm -f "$tempNodeEMailList" - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2025-Jan-10] ## -##----------------------------------------## -_CheckEMailConfigFileFromAMTM_() -{ - local doLogMsgs - - if [ $# -gt 0 ] && [ "$1" -eq 1 ] - then doLogMsgs=true - else doLogMsgs=false - fi - - isEMailConfigEnabledInAMTM=false - - if [ ! -f "$amtmMailConfFile" ] || [ ! -f "$amtmMailPswdFile" ] - then - "$doLogMsgs" && \ - Say "${REDct}**ERROR**${NOct}: Unable to send email notification [No config file]." - return 1 - fi - - FROM_NAME="" TO_NAME="" FROM_ADDRESS="" TO_ADDRESS="" - USERNAME="" SMTP="" PORT="" PROTOCOL="" - PASSWORD="" emailPwEnc="" - - # Custom Options ## - CC_NAME="" CC_ADDRESS="" - - . "$amtmMailConfFile" - - if [ -z "$TO_NAME" ] || [ -z "$USERNAME" ] || \ - [ -z "$FROM_ADDRESS" ] || [ -z "$TO_ADDRESS" ] || \ - [ -z "$SMTP" ] || [ -z "$PORT" ] || [ -z "$PROTOCOL" ] || \ - [ -z "$emailPwEnc" ] || [ "$PASSWORD" = "PUT YOUR PASSWORD HERE" ] - then - "$doLogMsgs" && \ - Say "${REDct}**ERROR**${NOct}: Unable to send email notification [Empty variables]." - return 1 - fi - - sendEMail_CC_Name="$(Get_Custom_Setting FW_New_Update_EMail_CC_Name)" - sendEMail_CC_Address="$(Get_Custom_Setting FW_New_Update_EMail_CC_Address)" - sendEMailNotificationsFlag="$(Get_Custom_Setting FW_New_Update_EMail_Notification)" - sendEMailFormaType="$(Get_Custom_Setting FW_New_Update_EMail_FormatType)" - if [ "$sendEMailFormaType" = "HTML" ] - then isEMailFormatHTML=true - else isEMailFormatHTML=false - fi - - if [ -n "$sendEMail_CC_Name" ] && [ "$sendEMail_CC_Name" != "TBD" ] && \ - [ -n "$sendEMail_CC_Address" ] && [ "$sendEMail_CC_Address" != "TBD" ] - then - [ -z "$CC_NAME" ] && CC_NAME="$sendEMail_CC_Name" - [ -z "$CC_ADDRESS" ] && CC_ADDRESS="$sendEMail_CC_Address" - fi - - isEMailConfigEnabledInAMTM=true - return 0 -} - -##------------------------------------------## -## Modified by ExtremeFiretop [2024-Dec-21] ## -##------------------------------------------## -_SendEMailNotification_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] || \ - [ "$sendEMailNotificationsFlag" != "ENABLED" ] || \ - ! _CheckEMailConfigFileFromAMTM_ 1 - then return 1 ; fi - - local CC_ADDRESS_STR="" CC_ADDRESS_ARG="" - - [ -z "$FROM_NAME" ] && FROM_NAME="$ScriptFNameTag" - [ -z "$FRIENDLY_ROUTER_NAME" ] && FRIENDLY_ROUTER_NAME="$MODEL_ID" - - ! _CreateEMailContent_ "$1" && return 1 - - [ "$1" = "POST_REBOOT_FW_UPDATE_SETUP" ] && return 0 - - if "$isInteractive" - then - printf "\nSending email notification [$1]." - printf "\nPlease wait...\n" - fi - - _UserTraceLog_ "SENDING email notification..." - - curl -Lv --retry 4 --retry-delay 5 --url "${PROTOCOL}://${SMTP}:${PORT}" \ - --mail-from "$FROM_ADDRESS" --mail-rcpt "$TO_ADDRESS" $CC_ADDRESS_ARG \ - --user "${USERNAME}:$(/usr/sbin/openssl aes-256-cbc "$emailPwEnc" -d -in "$amtmMailPswdFile" -pass pass:ditbabot,isoi)" \ - --upload-file "$tempEMailContent" \ - $SSL_FLAG --ssl-reqd --crlf >> "$userTraceFile" 2>&1 - curlCode="$?" - - if [ "$curlCode" -eq 0 ] - then - sleep 2 - rm -f "$userTraceFile" - Say "The email notification was sent successfully [$1]." - else - Say "${REDct}**ERROR**${NOct}: Failure to send email notification [Code: $curlCode][$1]." - fi - rm -f "$tempEMailContent" - - return "$curlCode" -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Jul-31] ## -##----------------------------------------## -# Directory for downloading & extracting firmware # -_CreateDirectory_() -{ - if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi - - mkdir -p "$1" - if [ ! -d "$1" ] - then - Say "${REDct}**ERROR**${NOct}: Unable to create directory [$1] to download firmware." - "$inMenuMode" && _WaitForEnterKey_ "$theMenuReturnPromptMsg" - return 1 - fi - if ! "$offlineUpdateTrigger" - then - # Clear directory in case any previous files still exist # - rm -f "${1}"/* - fi - return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-May-17] ## -##----------------------------------------## -_DelPostUpdateEmailNotifyScriptHook_() -{ - local hookScriptFile - - hookScriptFile="$hookScriptFPath" - if [ ! -f "$hookScriptFile" ] ; then return 1 ; fi - - if grep -qE "$POST_UPDATE_EMAIL_SCRIPT_JOB" "$hookScriptFile" - then - sed -i -e '/\/'"$ScriptFileName"' postUpdateEmail & '"$hookScriptTagStr"'/d' "$hookScriptFile" - if [ $? -eq 0 ] - then - Say "Post-update email notification hook was deleted successfully from '$hookScriptFile' script." - fi - else - Say "${GRNct}Post-update email notification hook is not found in '$hookScriptFile' script.${NOct}" - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2024-May-17] ## -##----------------------------------------## -_AddPostUpdateEmailNotifyScriptHook_() -{ - local hookScriptFile jobHookAdded=false - - hookScriptFile="$hookScriptFPath" - if [ ! -f "$hookScriptFile" ] - then - jobHookAdded=true - { - echo "#!/bin/sh" - echo "# $hookScriptFName" - echo "#" - echo "$POST_UPDATE_EMAIL_SCRIPT_HOOK" - } > "$hookScriptFile" - # - elif ! grep -qE "$POST_UPDATE_EMAIL_SCRIPT_JOB" "$hookScriptFile" - then - jobHookAdded=true - echo "$POST_UPDATE_EMAIL_SCRIPT_HOOK" >> "$hookScriptFile" - fi - chmod 0755 "$hookScriptFile" - - if "$jobHookAdded" - then Say "Post-update email notification hook was added successfully to '$hookScriptFile' script." - else Say "Post-update email notification hook already exists in '$hookScriptFile' script." - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2024-May-17] ## -##----------------------------------------## -_DelPostRebootRunScriptHook_() -{ - local hookScriptFile - - hookScriptFile="$hookScriptFPath" - if [ ! -f "$hookScriptFile" ] ; then return 1 ; fi - - if grep -qE "$POST_REBOOT_SCRIPT_JOB" "$hookScriptFile" - then - sed -i -e '/\/'"$ScriptFileName"' postRebootRun & '"$hookScriptTagStr"'/d' "$hookScriptFile" - if [ $? -eq 0 ] - then - Say "Post-reboot run hook was deleted successfully from '$hookScriptFile' script." - fi - else - Say "${GRNct}Post-reboot run hook is not found in '$hookScriptFile' script.${NOct}" - fi -} - -##----------------------------------------## -## Modified by Martinski W. [2024-May-17] ## -##----------------------------------------## -_AddPostRebootRunScriptHook_() -{ - local hookScriptFile jobHookAdded=false - - hookScriptFile="$hookScriptFPath" - if [ ! -f "$hookScriptFile" ] - then - jobHookAdded=true - { - echo "#!/bin/sh" - echo "# $hookScriptFName" - echo "#" - echo "$POST_REBOOT_SCRIPT_HOOK" - } > "$hookScriptFile" - # - elif ! grep -qE "$POST_REBOOT_SCRIPT_JOB" "$hookScriptFile" - then - jobHookAdded=true - echo "$POST_REBOOT_SCRIPT_HOOK" >> "$hookScriptFile" - fi - chmod 0755 "$hookScriptFile" - - if "$jobHookAdded" - then Say "Post-reboot run hook was added successfully to '$hookScriptFile' script." - else Say "Post-reboot run hook already exists in '$hookScriptFile' script." - fi - _WaitForEnterKey_ -} - -##----------------------------------------## -## Modified by Martinski W. [2024-May-31] ## -##----------------------------------------## -_GetCurrentFWInstalledLongVersion_() -{ - -##FOR TESTING/DEBUG ONLY## -if false ; then echo "3004.388.6.2" ; return 0 ; fi -##FOR TESTING/DEBUG ONLY## - - local theVersionStr extVersNum - - extVersNum="$fwInstalledExtendNum" - echo "$extVersNum" | grep -qiE "^(alpha|beta)" && extVersNum="0_$extVersNum" - [ -z "$extVersNum" ] && extVersNum=0 - - theVersionStr="${fwInstalledBuildVers}.$extVersNum" - [ -n "$fwInstalledBaseVers" ] && \ - theVersionStr="${fwInstalledBaseVers}.${theVersionStr}" - - echo "$theVersionStr" -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Mar-31] ## -##----------------------------------------## -_HasRouterMoreThan256MBtotalRAM_() -{ - local totalRAM_KB - totalRAM_KB="$(awk -F ' ' '/^MemTotal:/{print $2}' /proc/meminfo)" - [ -n "$totalRAM_KB" ] && [ "$totalRAM_KB" -gt 262144 ] && return 0 - return 1 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Apr-01] ## -##----------------------------------------## -#---------------------------------------------------------------------# -# The actual amount of RAM that is available for any new process -# (*without* using the swap file) can be roughly estimated from -# "Free Memory" & "Page Cache" (e.g. Inactive memory pages). -# This estimate must take into account that the overall system -# (kernel + native services + tmpfs) needs a minimum amount of RAM -# to continue to work, and that not all reclaimable Page Cache can -# be reclaimed because some may actually be in used at the time. -# NOTE: [Martinski] -# Since reported "Available RAM" estimates tend to be extremely -# conservative in many cases, we decided to take another approach -# and calculate it based on the reported "Free RAM" plus ~66% of -# reported "Memory Cached" and then take the largest of the two -# values: Reported "Available RAM" vs Calculated "Available RAM" -# While still somewhat conservative, this would provide a better -# estimate, especially at the time when the router is about to -# shut down and terminate all non-critical services/processes -# before the actual F/W flash is performed. -#---------------------------------------------------------------------# -_GetAvailableRAM_KB_() -{ - local theMemAvailable_KB theMemAvail_KB theMemCache_KB - local theMemFree1_KB theMemFree2_KB inactivePgs_KB - - _MaxNumber_() { echo "$(($1 < $2 ? $2 : $1))" ; } - - theMemCache_KB="$(awk -F ' ' '/^Cached:/{print $2}' /proc/meminfo)" - theMemFree1_KB="$(awk -F ' ' '/^MemFree:/{print $2}' /proc/meminfo)" - theMemAvail_KB="$(awk -F ' ' '/^MemAvailable:/{print $2}' /proc/meminfo)" - # Assumes that only ~66% of Page Cache can be reclaimed # - theMemFree2_KB="$((theMemFree1_KB + ((theMemCache_KB * 2) / 3)))" - - if [ -z "$theMemAvail_KB" ] - then - inactivePgs_KB="$(awk -F ' ' '/^Inactive:/{print $2}' /proc/meminfo)" - theMemAvail_KB="$((theMemFree1_KB + inactivePgs_KB))" - fi - theMemAvailable_KB="$(_MaxNumber_ "$theMemAvail_KB" "$theMemFree2_KB")" - echo "$theMemAvailable_KB" ; return 0 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Mar-31] ## -##----------------------------------------## -_GetFreeRAM_KB_() -{ - awk -F ' ' '/^MemFree:/{print $2}' /proc/meminfo - ##FOR DEBUG ONLY## echo 1000 -} - -##----------------------------------------## -## Modified by Martinski W. [2024-Jun-05] ## -##----------------------------------------## -_GetRequiredRAM_KB_() -{ - local theURL="$1" - local zip_file_size_bytes zip_file_size_kb overhead_kb - local total_required_kb overhead_percentage=50 - - # Size of the ZIP file in bytes # - zip_file_size_bytes="$(curl -LsI --retry 4 --retry-delay 5 "$theURL" | grep -i Content-Length | tail -1 | awk '{print $2}')" - # Bytes to KBytes # - zip_file_size_kb="$((zip_file_size_bytes / 1024))" - - # Calculate overhead based on the percentage # - overhead_kb="$((zip_file_size_kb * overhead_percentage / 100))" - - total_required_kb="$((zip_file_size_kb + overhead_kb))" - echo "$total_required_kb" -} - -##----------------------------------------## -## Modified by Martinski W. [2023-Mar-24] ## -##----------------------------------------## -_ShutDownNonCriticalServices_() -{ - for procName in nt_center nt_monitor nt_actMail - do - procNum="$(ps w | grep -w "$procName" | grep -cv "grep -w")" - if [ "$procNum" -gt 0 ] - then - printf "$procName: [$procNum]\n" - killall -9 "$procName" && sleep 1 - fi - done - - for service_name in conn_diag samba nasapps - do - procNum="$(ps w | grep -w "$service_name" | grep -cv "grep -w")" - if [ "$procNum" -gt 0 ] - then - printf "$service_name: [$procNum]\n" - service "stop_$service_name" && sleep 1 - fi - done -} - -##------------------------------------------## -## Modified by ExtremeFiretop [2024-Jan-26] ## -##------------------------------------------## -_DoCleanUp_() -{ - local delBINfiles=false keepZIPfile=false keepWfile=false - - local doTrace=false - [ $# -gt 0 ] && [ "$1" -eq 0 ] && doTrace=false - if "$doTrace" - then - Say "START _DoCleanUp_" - _UserTraceLog_ "START _DoCleanUp_" - fi - - [ $# -gt 0 ] && [ "$1" -eq 1 ] && delBINfiles=true - [ $# -gt 1 ] && [ "$2" -eq 1 ] && keepZIPfile=true - [ $# -gt 2 ] && [ "$3" -eq 1 ] && keepWfile=true - - # Stop the LEDs blinking # - _Reset_LEDs_ 1 - - # Check existence of files and preserve based on flags # - local moveZIPback=false moveWback=false - - # Move file temporarily to save it from deletion # - "$keepZIPfile" && [ -f "$FW_ZIP_FPATH" ] && \ - mv -f "$FW_ZIP_FPATH" "${FW_ZIP_BASE_DIR}/$ScriptDirNameD" && moveZIPback=true - - if "$keepWfile" && [ -f "$FW_DL_FPATH" ]; then - mv -f "$FW_DL_FPATH" "${FW_ZIP_BASE_DIR}/$ScriptDirNameD" && moveWback=true - fi - - rm -f "${FW_ZIP_DIR:?}"/* - "$delBINfiles" && rm -f "${FW_BIN_DIR:?}"/* - - # Move files back to their original location if needed # - "$moveZIPback" && \ - mv -f "${FW_ZIP_BASE_DIR}/${ScriptDirNameD}/${FW_FileName}.zip" "$FW_ZIP_FPATH" - - "$moveWback" && \ - mv -f "${FW_ZIP_BASE_DIR}/${ScriptDirNameD}/${FW_FileName}.${extension}" "$FW_DL_FPATH" - - if "$doTrace" - then - Say "EXIT _DoCleanUp_" - _UserTraceLog_ "EXIT _DoCleanUp_" - fi + + + + + + + + + + + + +MerlinAU add-on for ASUSWRT-Merlin Firmware + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + +" /> +" /> + +" /> + +" /> +" /> +" /> +" /> +" /> +" /> + + + + + + + + +
  + + + + + + + +
+ + + +
+
 
+
MerlinAU
+
+
This is the MerlinAU add-on integrated into the router WebUI +[ + Wiki ] + +
+
 
+ + + + + + + + +
+ + + + + + + + + + + +
Firmware Status (click to expand/collapse)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
F/W Product/Model ID:
F/W Variant Detected:Unknown
F/W Version Installed: + <% nvram_get("firmver"); %>.<% nvram_get("buildno"); %>.<% nvram_get("extendno"); %> +
F/W Update Available:NONE FOUND
Estimated Update Time:TBD
Last Notification Date:TBD
Changelog Approval:Disabled
+ + + + + + + + + + + +
Settings Status (click to expand/collapse)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
F/W Update Check:Disabled
Changelog Check:Disabled
Beta-to-Release Updates:Disabled
Tailscale VPN Access:Disabled
Automatic Backups:Disabled
Auto-Updates for MerlinAU:Disabled
Email Notifications:Disabled
+ +
 
+ + + + + + +
Actions (click to expand/collapse)
+
+ ++ + + + + + + +
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
 
+ + + + + + + + + + +
Configuration (click to expand/collapse)
+ + ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+ +
+
+
+
+ +
+
+ + +
+ + + +
+ + + +
+ + +
+ Days: + + + + +
+ + + + + + + +
+
+
+ Hour: + +
+
+ Minutes: + +
+
+ + + +
+ + + +
+ +
+ +
+ +
+ + + + +
+ + + + +
+ + + + +
+ +
+ +
+
+ +
+
+
MerlinAU
+
+ + + From c94c253f9caf764ecdfeec50de412904d58e951c Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Mon, 7 Apr 2025 09:14:09 -0400 Subject: [PATCH 05/15] Update MerlinAU.sh --- MerlinAU.sh | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index 253df58f..0127599b 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -2159,27 +2159,24 @@ _CheckFor_WebGUI_Page_() if "$mountWebGUI_OK" && \ [ "$(_Check_WebGUI_Page_Exists_)" = "NONE" ] then - updatedWebUIPage=false - # Only try to download if the local .asp file does NOT exist: - if [ ! -f "$SCRIPT_WEB_ASP_FILE" ] - then - if _CurlFileDownload_ "$SCRIPT_WEB_ASP_FILE" "$SCRIPT_WEB_ASP_PATH" - then - chmod 664 "$SCRIPT_WEB_ASP_PATH" - if "$updatedWebUIPage" - then - theWebPage="$(_GetWebUIPage_ "$SCRIPT_WEB_ASP_PATH")" - if [ -n "$theWebPage" ] && [ "$theWebPage" != "NONE" ] - then - sed -i "/url: \"$theWebPage\", tabName: \"$SCRIPT_NAME\"/d" "$TEMP_MENU_TREE" - rm -f "${SHARED_WEB_DIR}/$theWebPage" - rm -f "${SHARED_WEB_DIR}/$(echo "$theWebPage" | cut -f1 -d'.').title" - fi - _Mount_WebUI_ + updatedWebUIPage=false + # Only try to download if the local .asp file does NOT exist: + if [ ! -f "$SCRIPT_WEB_ASP_FILE" ] + then + if _CurlFileDownload_ "$SCRIPT_WEB_ASP_FILE" "$SCRIPT_WEB_ASP_PATH" + then + chmod 664 "$SCRIPT_WEB_ASP_PATH" + theWebPage="$(_GetWebUIPage_ "$SCRIPT_WEB_ASP_PATH")" + if [ -n "$theWebPage" ] && [ "$theWebPage" != "NONE" ] + then + sed -i "/url: \"$theWebPage\", tabName: \"$SCRIPT_NAME\"/d" "$TEMP_MENU_TREE" + rm -f "${SHARED_WEB_DIR}/$theWebPage" + rm -f "${SHARED_WEB_DIR}/$(echo "$theWebPage" | cut -f1 -d'.').title" fi + _Mount_WebUI_ else Say "${REDct}**ERROR**${NOct}: Unable to download latest WebUI ASP file for $SCRIPT_NAME." - fi + fi else _Mount_WebUI_ fi From d4c12c953fa7def959fa913883f2bc8e044024eb Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Mon, 7 Apr 2025 09:16:24 -0400 Subject: [PATCH 06/15] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f300d7d0..e23e13b1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MerlinAU - AsusWRT-Merlin Firmware Auto Updater -## v1.4.0 -## 2025-Apr-06 +## v1.4.1 +## 2025-Apr-07 ## WebUI: ![image](https://github.com/user-attachments/assets/92701007-a902-4724-9bae-b255856a686a) From a0b7907696c083f0b8158cd52f94841240a6ed1b Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Mon, 7 Apr 2025 09:16:58 -0400 Subject: [PATCH 07/15] Update version.txt --- version.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.txt b/version.txt index 9c0eb14b..93ff4355 100644 --- a/version.txt +++ b/version.txt @@ -1,2 +1,2 @@ -1.4.0 -25040600 +1.4.1 +25040709 From 0e3e28dbebfc521c802d8ff8ebf8ed3e27a77d9a Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Mon, 7 Apr 2025 09:19:16 -0400 Subject: [PATCH 08/15] Update MerlinAU.sh --- MerlinAU.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index 0127599b..eea31ffb 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -2158,8 +2158,7 @@ _CheckFor_WebGUI_Page_() { if "$mountWebGUI_OK" && \ [ "$(_Check_WebGUI_Page_Exists_)" = "NONE" ] - then - updatedWebUIPage=false + then # Only try to download if the local .asp file does NOT exist: if [ ! -f "$SCRIPT_WEB_ASP_FILE" ] then From 7fbdc16c0adbdc0068548a8e3c26e479c7170891 Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Mon, 7 Apr 2025 13:01:11 -0400 Subject: [PATCH 09/15] Missing Install Parameter for Script Missing Install Parameter for Script --- MerlinAU.sh | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index eea31ffb..f8be2379 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -176,6 +176,14 @@ keepConfigFile=false bypassPostponedDays=false runLoginCredentialsTest=false +##---------------------------------------## +## Added by ExtremeFiretop [2025-Apr-07] ## +##---------------------------------------## +MerlinAUInstall=$(grep -F '#MerlinAU#' /jffs/scripts/services-start) +if [ -z "$MerlinAUInstall" ] && tty >/dev/null 2>&1; then + set "install" +fi + # Main LAN Network Info # readonly myLAN_HostName="$(nvram get lan_hostname)" readonly mainLAN_IFname="$(nvram get lan_ifname)" @@ -2151,35 +2159,14 @@ _Mount_WebUI_() return 0 } -##------------------------------------------## -## Modified by ExtremeFiretop [2025-Apr-07] ## -##------------------------------------------## +##-------------------------------------## +## Added by Martinski W. [2025-Feb-12] ## +##-------------------------------------## _CheckFor_WebGUI_Page_() { - if "$mountWebGUI_OK" && \ - [ "$(_Check_WebGUI_Page_Exists_)" = "NONE" ] - then - # Only try to download if the local .asp file does NOT exist: - if [ ! -f "$SCRIPT_WEB_ASP_FILE" ] - then - if _CurlFileDownload_ "$SCRIPT_WEB_ASP_FILE" "$SCRIPT_WEB_ASP_PATH" - then - chmod 664 "$SCRIPT_WEB_ASP_PATH" - theWebPage="$(_GetWebUIPage_ "$SCRIPT_WEB_ASP_PATH")" - if [ -n "$theWebPage" ] && [ "$theWebPage" != "NONE" ] - then - sed -i "/url: \"$theWebPage\", tabName: \"$SCRIPT_NAME\"/d" "$TEMP_MENU_TREE" - rm -f "${SHARED_WEB_DIR}/$theWebPage" - rm -f "${SHARED_WEB_DIR}/$(echo "$theWebPage" | cut -f1 -d'.').title" - fi - _Mount_WebUI_ - else - Say "${REDct}**ERROR**${NOct}: Unable to download latest WebUI ASP file for $SCRIPT_NAME." - fi - else - _Mount_WebUI_ - fi - fi + if "$mountWebGUI_OK" && \ + [ "$(_Check_WebGUI_Page_Exists_)" = "NONE" ] + then _Mount_WebUI_ ; fi } ##----------------------------------------## From d26c90d0fcc8bf8f8e1597c3586d5f839543aa45 Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 7 Apr 2025 18:32:56 -0700 Subject: [PATCH 10/15] Fixes & Improvements 1) Modified code to check and make sure the WebGUI ASP file is downloaded and installed. 2) Modified code to check and make sure all configuration default settings are initialized. --- MerlinAU.sh | 239 ++++++++++++++++++++++++++++++++++------------------ version.txt | 2 +- 2 files changed, 160 insertions(+), 81 deletions(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index f8be2379..b86f16c3 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -176,14 +176,6 @@ keepConfigFile=false bypassPostponedDays=false runLoginCredentialsTest=false -##---------------------------------------## -## Added by ExtremeFiretop [2025-Apr-07] ## -##---------------------------------------## -MerlinAUInstall=$(grep -F '#MerlinAU#' /jffs/scripts/services-start) -if [ -z "$MerlinAUInstall" ] && tty >/dev/null 2>&1; then - set "install" -fi - # Main LAN Network Info # readonly myLAN_HostName="$(nvram get lan_hostname)" readonly mainLAN_IFname="$(nvram get lan_ifname)" @@ -1146,9 +1138,9 @@ _UpdateLoginPswdCheckHelper_() } ##----------------------------------------## -## Modified by Martinski W. [2025-Mar-07] ## +## Modified by Martinski W. [2025-Apr-07] ## ##----------------------------------------## -_InitCustomSettingsConfig_() +_InitCustomDefaultsConfig_() { [ ! -d "$SETTINGS_DIR" ] && mkdir -m 755 -p "$SETTINGS_DIR" @@ -1185,53 +1177,99 @@ _InitCustomSettingsConfig_() if ! grep -q "^FW_New_Update_Notification_Date " "$CONFIG_FILE" then - sed -i "1 i FW_New_Update_Notification_Date TBD" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 1 ] + then echo "FW_New_Update_Notification_Date TBD" >> "$CONFIG_FILE" + else sed -i "1 i FW_New_Update_Notification_Date TBD" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_New_Update_Notification_Vers " "$CONFIG_FILE" then - sed -i "2 i FW_New_Update_Notification_Vers TBD" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 2 ] + then echo "FW_New_Update_Notification_Vers TBD" >> "$CONFIG_FILE" + else sed -i "2 i FW_New_Update_Notification_Vers TBD" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_New_Update_Postponement_Days=" "$CONFIG_FILE" then - sed -i "3 i FW_New_Update_Postponement_Days=$FW_UpdateDefaultPostponementDays" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 3 ] + then echo "FW_New_Update_Postponement_Days=$FW_UpdateDefaultPostponementDays" >> "$CONFIG_FILE" + else sed -i "3 i FW_New_Update_Postponement_Days=$FW_UpdateDefaultPostponementDays" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_New_Update_EMail_Notification " "$CONFIG_FILE" then - sed -i "4 i FW_New_Update_EMail_Notification $FW_UpdateEMailNotificationDefault" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 4 ] + then echo "FW_New_Update_EMail_Notification $FW_UpdateEMailNotificationDefault" >> "$CONFIG_FILE" + else sed -i "4 i FW_New_Update_EMail_Notification $FW_UpdateEMailNotificationDefault" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_New_Update_EMail_FormatType=" "$CONFIG_FILE" then - sed -i "5 i FW_New_Update_EMail_FormatType=\"${FW_UpdateEMailFormatTypeDefault}\"" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 5 ] + then echo "FW_New_Update_EMail_FormatType=\"${FW_UpdateEMailFormatTypeDefault}\"" >> "$CONFIG_FILE" + else sed -i "5 i FW_New_Update_EMail_FormatType=\"${FW_UpdateEMailFormatTypeDefault}\"" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_New_Update_Cron_Job_Schedule=" "$CONFIG_FILE" then - sed -i "6 i FW_New_Update_Cron_Job_Schedule=\"${FW_Update_CRON_DefaultSchedule}\"" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 6 ] + then echo "FW_New_Update_Cron_Job_Schedule=\"${FW_Update_CRON_DefaultSchedule}\"" >> "$CONFIG_FILE" + else sed -i "6 i FW_New_Update_Cron_Job_Schedule=\"${FW_Update_CRON_DefaultSchedule}\"" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_New_Update_ZIP_Directory_Path=" "$CONFIG_FILE" then - sed -i "7 i FW_New_Update_ZIP_Directory_Path=\"${FW_Update_ZIP_DefaultSetupDIR}\"" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 7 ] + then echo "FW_New_Update_ZIP_Directory_Path=\"${FW_Update_ZIP_DefaultSetupDIR}\"" >> "$CONFIG_FILE" + else sed -i "7 i FW_New_Update_ZIP_Directory_Path=\"${FW_Update_ZIP_DefaultSetupDIR}\"" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_New_Update_LOG_Directory_Path=" "$CONFIG_FILE" then - sed -i "8 i FW_New_Update_LOG_Directory_Path=\"${FW_Update_LOG_BASE_DefaultDIR}\"" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 8 ] + then echo "FW_New_Update_LOG_Directory_Path=\"${FW_Update_LOG_BASE_DefaultDIR}\"" >> "$CONFIG_FILE" + else sed -i "8 i FW_New_Update_LOG_Directory_Path=\"${FW_Update_LOG_BASE_DefaultDIR}\"" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_New_Update_LOG_Preferred_Path=" "$CONFIG_FILE" then preferredPath="$(Get_Custom_Setting FW_New_Update_LOG_Directory_Path)" - sed -i "9 i FW_New_Update_LOG_Preferred_Path=\"${preferredPath}\"" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 9 ] + then echo "FW_New_Update_LOG_Preferred_Path=\"${preferredPath}\"" >> "$CONFIG_FILE" + else sed -i "9 i FW_New_Update_LOG_Preferred_Path=\"${preferredPath}\"" "$CONFIG_FILE" + fi + retCode=1 + fi + if ! grep -q "^FW_New_Update_EMail_CC_Name=" "$CONFIG_FILE" + then + if [ "$(wc -l < "$CONFIG_FILE")" -lt 10 ] + then echo "FW_New_Update_EMail_CC_Name=TBD" >> "$CONFIG_FILE" + else sed -i "10 i FW_New_Update_EMail_CC_Name=TBD" "$CONFIG_FILE" + fi + retCode=1 + fi + if ! grep -q "^FW_New_Update_EMail_CC_Address=" "$CONFIG_FILE" + then + if [ "$(wc -l < "$CONFIG_FILE")" -lt 11 ] + then echo "FW_New_Update_EMail_CC_Address=TBD" >> "$CONFIG_FILE" + else sed -i "11 i FW_New_Update_EMail_CC_Address=TBD" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^credentials_base64 " "$CONFIG_FILE" then - sed -i "10 i credentials_base64 TBD" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 12 ] + then echo "credentials_base64 TBD" >> "$CONFIG_FILE" + else sed -i "12 i credentials_base64 TBD" "$CONFIG_FILE" + fi _UpdateLoginPswdCheckHelper_ InitPWD retCode=1 else @@ -1239,32 +1277,50 @@ _InitCustomSettingsConfig_() fi if ! grep -q "^CheckChangeLog " "$CONFIG_FILE" then - sed -i "11 i CheckChangeLog ENABLED" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 13 ] + then echo "CheckChangeLog ENABLED" >> "$CONFIG_FILE" + else sed -i "13 i CheckChangeLog ENABLED" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_Update_Check " "$CONFIG_FILE" then - sed -i "12 i FW_Update_Check TBD" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 14 ] + then echo "FW_Update_Check TBD" >> "$CONFIG_FILE" + else sed -i "14 i FW_Update_Check TBD" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^Allow_Updates_OverVPN " "$CONFIG_FILE" then - sed -i "13 i Allow_Updates_OverVPN DISABLED" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 15 ] + then echo "Allow_Updates_OverVPN DISABLED" >> "$CONFIG_FILE" + else sed -i "15 i Allow_Updates_OverVPN DISABLED" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^FW_Allow_Beta_Production_Up " "$CONFIG_FILE" then - sed -i "14 i FW_Allow_Beta_Production_Up ENABLED" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 16 ] + then echo "FW_Allow_Beta_Production_Up ENABLED" >> "$CONFIG_FILE" + else sed -i "16 i FW_Allow_Beta_Production_Up ENABLED" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^Allow_Script_Auto_Update " "$CONFIG_FILE" then - sed -i "15 i Allow_Script_Auto_Update DISABLED" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 17 ] + then echo "Allow_Script_Auto_Update DISABLED" >> "$CONFIG_FILE" + else sed -i "17 i Allow_Script_Auto_Update DISABLED" "$CONFIG_FILE" + fi retCode=1 fi if ! grep -q "^Script_Update_Cron_Job_SchedDays=" "$CONFIG_FILE" then - sed -i "16 i Script_Update_Cron_Job_SchedDays=\"${SW_Update_CRON_DefaultSchedDays}\"" "$CONFIG_FILE" + if [ "$(wc -l < "$CONFIG_FILE")" -lt 18 ] + then echo "Script_Update_Cron_Job_SchedDays=\"${SW_Update_CRON_DefaultSchedDays}\"" >> "$CONFIG_FILE" + else sed -i "18 i Script_Update_Cron_Job_SchedDays=\"${SW_Update_CRON_DefaultSchedDays}\"" "$CONFIG_FILE" + fi retCode=1 fi dos2unix "$CONFIG_FILE" @@ -1273,6 +1329,32 @@ _InitCustomSettingsConfig_() return "$retCode" } +##-------------------------------------## +## Added by Martinski W. [2025-Apr-07] ## +##-------------------------------------## +_InitCustomUserSettings_() +{ + FW_UpdateCronJobSchedule="$(Get_Custom_Setting FW_New_Update_Cron_Job_Schedule)" + ScriptAutoUpdateSetting="$(Get_Custom_Setting Allow_Script_Auto_Update)" + ScriptUpdateCronSchedDays="$(Get_Custom_Setting Script_Update_Cron_Job_SchedDays)" + + FW_UpdatePostponementDays="$(Get_Custom_Setting FW_New_Update_Postponement_Days)" + FW_UpdateExpectedRunDate="$(Get_Custom_Setting FW_New_Update_Expected_Run_Date)" + + # F/W Update Email Notifications # + sendEMailFormaType="$(Get_Custom_Setting FW_New_Update_EMail_FormatType)" + sendEMailNotificationsFlag="$(Get_Custom_Setting FW_New_Update_EMail_Notification)" + sendEMail_CC_Name="$(Get_Custom_Setting FW_New_Update_EMail_CC_Name)" + sendEMail_CC_Address="$(Get_Custom_Setting FW_New_Update_EMail_CC_Address)" + if [ "$sendEMailFormaType" = "HTML" ] + then isEMailFormatHTML=true + else isEMailFormatHTML=false + fi + + _SetUp_FW_UpdateZIP_DirectoryPaths_ + _SetUp_FW_UpdateLOG_DirectoryPaths_ +} + ##----------------------------------------## ## Modified by Martinski W. [2025-Jan-05] ## ##----------------------------------------## @@ -1982,40 +2064,23 @@ readonly hookScriptFName="services-start" readonly hookScriptFPath="${SCRIPTS_PATH}/$hookScriptFName" readonly hookScriptTagStr="#Added by $ScriptFNameTag#" -# Postponement Days for F/W Update Check # -FW_UpdatePostponementDays="$(Get_Custom_Setting FW_New_Update_Postponement_Days)" -FW_UpdateExpectedRunDate="$(Get_Custom_Setting FW_New_Update_Expected_Run_Date)" - ##----------------------------------------## -## Modified by Martinski W. [2024-Feb-18] ## +## Modified by Martinski W. [2025-Apr-07] ## ##----------------------------------------## # F/W Update Email Notifications # isEMailFormatHTML=true isEMailConfigEnabledInAMTM=false -sendEMailFormaType="$(Get_Custom_Setting FW_New_Update_EMail_FormatType)" -sendEMailNotificationsFlag="$(Get_Custom_Setting FW_New_Update_EMail_Notification)" -sendEMail_CC_Name="$(Get_Custom_Setting FW_New_Update_EMail_CC_Name)" -sendEMail_CC_Address="$(Get_Custom_Setting FW_New_Update_EMail_CC_Address)" -if [ "$sendEMailFormaType" = "HTML" ] -then isEMailFormatHTML=true -else isEMailFormatHTML=false -fi ##----------------------------------------## -## Modified by Martinski W. [2024-Nov-27] ## +## Modified by Martinski W. [2025-Apr-07] ## ##----------------------------------------## # Define the CRON job command to execute # -# Define the hook script file to be used # -ScriptAutoUpdateSetting="$(Get_Custom_Setting Allow_Script_Auto_Update)" -ScriptUpdateCronSchedDays="$(Get_Custom_Setting Script_Update_Cron_Job_SchedDays)" - readonly SCRIPT_UP_CRON_JOB_RUN="sh $ScriptFilePath checkupdates" readonly SCRIPT_UP_CRON_JOB_TAG="${ScriptFNameTag}_ScriptUpdate" readonly DAILY_SCRIPT_UPDATE_CHECK_JOB="sh $ScriptFilePath scriptAUCronJob & $hookScriptTagStr" readonly DAILY_SCRIPT_UPDATE_CHECK_HOOK="[ -f $ScriptFilePath ] && $DAILY_SCRIPT_UPDATE_CHECK_JOB" # Define the CRON job command to execute # -FW_UpdateCronJobSchedule="$(Get_Custom_Setting FW_New_Update_Cron_Job_Schedule)" readonly CRON_JOB_RUN="sh $ScriptFilePath run_now" readonly CRON_JOB_TAG_OLD="$ScriptFNameTag" readonly CRON_JOB_TAG="${ScriptFNameTag}_FWUpdate" @@ -2159,14 +2224,23 @@ _Mount_WebUI_() return 0 } -##-------------------------------------## -## Added by Martinski W. [2025-Feb-12] ## -##-------------------------------------## +##----------------------------------------## +## Modified by Martinski W. [2025-Apr-07] ## +##----------------------------------------## _CheckFor_WebGUI_Page_() { - if "$mountWebGUI_OK" && \ + if "$mountWebGUI_OK" && \ [ "$(_Check_WebGUI_Page_Exists_)" = "NONE" ] - then _Mount_WebUI_ ; fi + then + if [ ! -s "$SCRIPT_WEB_ASP_PATH" ] + then + _ReleaseLock_ + exec "$ScriptFilePath" install + exit 0 + else + _Mount_WebUI_ + fi + fi } ##----------------------------------------## @@ -5073,9 +5147,9 @@ _toggle_change_log_check_() _WaitForEnterKey_ } -##------------------------------------------## -## Modified by ExtremeFiretop [2024-Jul-23] ## -##------------------------------------------## +##----------------------------------------## +## Modified by Martinski W. [2025-Apr-07] ## +##----------------------------------------## _Toggle_VPN_Access_() { local currentSetting="$(Get_Custom_Setting "Allow_Updates_OverVPN")" @@ -5086,23 +5160,23 @@ _Toggle_VPN_Access_() printf "Disabling this feature will shut down Tailscale/ZeroTier VPN access during updates.\n" printf "Proceed if you do not need remote VPN access during firmware updates.\n" - if _WaitForYESorNO_ "\nProceed to ${GRNct}DISABLE${NOct}?" + if _WaitForYESorNO_ "\nProceed to ${REDct}DISABLE${NOct}?" then Update_Custom_Settings "Allow_Updates_OverVPN" "DISABLED" - printf "VPN access will now be ${GRNct}DISABLED.${NOct}\n" + printf "VPN access will now be ${REDct}DISABLED.${NOct}\n" else - printf "VPN access during updates remains ${REDct}ENABLED.${NOct}\n" + printf "VPN access during updates remains ${GRNct}ENABLED.${NOct}\n" fi else printf "\n${REDct}*WARNING*${NOct}\n" printf "Enabling this feature will keep Tailscale/ZeroTier VPN access active during updates.\n" printf "Proceed only if you require Tailscale/ZeroTier to connect remotely via an SSH session during firmware updates.\n" - if _WaitForYESorNO_ "\nProceed to ${REDct}ENABLE${NOct}?" + if _WaitForYESorNO_ "\nProceed to ${GRNct}ENABLE${NOct}?" then Update_Custom_Settings "Allow_Updates_OverVPN" "ENABLED" - printf "VPN access will now be ${REDct}ENABLED.${NOct}\n" + printf "VPN access will now be ${GRNct}ENABLED.${NOct}\n" else - printf "VPN access during updates remains ${GRNct}DISABLED.${NOct}\n" + printf "VPN access during updates remains ${REDct}DISABLED.${NOct}\n" fi fi _WaitForEnterKey_ @@ -9223,7 +9297,8 @@ _CheckForMinimumRequirements_() _DoStartupInit_() { _CreateDirPaths_ - _InitCustomSettingsConfig_ + _InitCustomDefaultsConfig_ + _InitCustomUserSettings_ _CreateSymLinks_ _InitHelperJSFile_ _SetVersionSharedSettings_ local "$SCRIPT_VERSION" @@ -9237,21 +9312,24 @@ _DoStartupInit_() } ##----------------------------------------## -## Modified by Martinski W. [2025-Jan-15] ## +## Modified by Martinski W. [2025-Apr-07] ## ##----------------------------------------## _DoInstallation_() { local webguiOK=true - + if ! _AcquireLock_ cliFileLock ; then return 1 ; fi _CreateDirPaths_ - _InitCustomSettingsConfig_ + _InitCustomDefaultsConfig_ + _InitCustomUserSettings_ _CreateSymLinks_ _InitHelperJSFile_ _SetVersionSharedSettings_ local "$SCRIPT_VERSION" _SetVersionSharedSettings_ server "$SCRIPT_VERSION" _DownloadScriptFiles_ install + _CheckAndSetBackupOption_ + _SetDefaultBuildType_ if "$mountWebGUI_OK" then @@ -9595,12 +9673,13 @@ then _ReleaseLock_ ; exit 0 fi -##------------------------------------------## -## Modified by ExtremeFiretop [2025-Apr-07] ## -##------------------------------------------## +##---------------------------------------## +## Added by ExtremeFiretop [2025-Feb-08] ## +##---------------------------------------## _CheckAndSetBackupOption_() { - local currentBackupOption="$(Get_Custom_Setting "FW_Auto_Backupmon")" + local currentBackupOption + currentBackupOption="$(Get_Custom_Setting "FW_Auto_Backupmon")" if [ -f "/jffs/scripts/backupmon.sh" ] then # If setting is empty, add it to the configuration file # @@ -9668,16 +9747,15 @@ _EnableFWAutoUpdateChecks_() fi } -##------------------------------------------## -## Modified by ExtremeFiretop [2025-Apr-07] ## -##------------------------------------------## +##----------------------------------------## +## Modified by Martinski W. [2025-Jan-12] ## +##----------------------------------------## _ConfirmCronJobForFWAutoUpdates_() { if [ $# -gt 0 ] && [ -n "$1" ] && \ echo "$1" | grep -qE "^(install|startup)$" then return 1 ; fi - FW_UpdateCronJobSchedule="$(Get_Custom_Setting FW_New_Update_Cron_Job_Schedule)" # Check if the PREVIOUS Cron Job ID already exists # if eval $cronListCmd | grep -qE "$CRON_JOB_RUN #${CRON_JOB_TAG_OLD}#$" then #If it exists, delete the OLD one & create a NEW one# @@ -10263,9 +10341,9 @@ _ShowAdvancedOptionsMenu_() printf "\n ${GRNct}4${NOct}. Toggle Tailscale/ZeroTier Access During Updates" if [ "$VPNAccess" = "DISABLED" ] then - printf "\n${padStr}[Currently ${GRNct}DISABLED${NOct}]\n" + printf "\n${padStr}[Currently ${REDct}DISABLED${NOct}]\n" else - printf "\n${padStr}[Currently ${REDct}ENABLED${NOct}]\n" + printf "\n${padStr}[Currently ${GRNct}ENABLED${NOct}]\n" fi # Check if the file BACKUPMON exists # @@ -10691,9 +10769,9 @@ _MainMenu_() done } -##------------------------------------------## -## Modified by ExtremeFiretop [2025-Apr-07] ## -##------------------------------------------## +##-------------------------------------## +## Added by Martinski W. [2025-Jan-15] ## +##-------------------------------------## _DoInitializationStartup_() { if ! _CheckForMinimumRequirements_ @@ -10702,15 +10780,13 @@ _DoInitializationStartup_() _DoExit_ 1 fi - _CheckAndSetBackupOption_ - _SetDefaultBuildType_ - if [ $# -gt 0 ] && [ -n "$1" ] && \ echo "$1" | grep -qE "^(install|startup)$" then return 1 ; fi _CreateDirPaths_ - _InitCustomSettingsConfig_ + _InitCustomDefaultsConfig_ + _InitCustomUserSettings_ _CreateSymLinks_ _InitHelperJSFile_ _SetVersionSharedSettings_ local "$SCRIPT_VERSION" @@ -10720,6 +10796,9 @@ _DoInitializationStartup_() _AutoStartupHook_ create 2>/dev/null _AutoServiceEvent_ create 2>/dev/null fi + + _CheckAndSetBackupOption_ + _SetDefaultBuildType_ } FW_InstalledVersion="$(_GetCurrentFWInstalledLongVersion_)" diff --git a/version.txt b/version.txt index 93ff4355..a0b0a6f8 100644 --- a/version.txt +++ b/version.txt @@ -1,2 +1,2 @@ 1.4.1 -25040709 +25040718 From 602d6a8f38629a37c59a4bdd5e09eae1cce6a742 Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 7 Apr 2025 23:00:42 -0700 Subject: [PATCH 11/15] Check for Version File --- MerlinAU.sh | 17 ++++++++++++++++- version.txt | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index b86f16c3..f8efd2f1 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -2243,6 +2243,19 @@ _CheckFor_WebGUI_Page_() fi } +##-------------------------------------## +## Added by Martinski W. [2025-Apr-07] ## +##-------------------------------------## +_CheckFor_VersionFile_() +{ + if [ ! -s "$SCRIPT_VERPATH" ] + then + _ReleaseLock_ + exec "$ScriptFilePath" install + exit 0 + fi +} + ##----------------------------------------## ## Modified by Martinski W. [2025-Jan-11] ## ##----------------------------------------## @@ -10806,7 +10819,7 @@ FW_InstalledVerStr="${GRNct}${FW_InstalledVersion}${NOct}" FW_NewUpdateVerInit=TBD ##----------------------------------------## -## Modified by Martinski W. [2025-Feb-12] ## +## Modified by Martinski W. [2025-Apr-07] ## ##----------------------------------------## if [ $# -eq 0 ] || [ -z "$1" ] || \ { [ $# -gt 1 ] && [ "$1" = "reload" ] ; } @@ -10823,8 +10836,10 @@ then fi if [ "$ScriptAutoUpdateSetting" = "ENABLED" ] then _AddScriptAutoUpdateCronJob_ ; fi + _ConfirmCronJobForFWAutoUpdates_ _CheckFor_WebGUI_Page_ + _CheckFor_VersionFile_ _MainMenu_ "$@" _DoExit_ 0 diff --git a/version.txt b/version.txt index a0b0a6f8..9cb45e5b 100644 --- a/version.txt +++ b/version.txt @@ -1,2 +1,2 @@ 1.4.1 -25040718 +25040723 From 5f3583e3aa233a88ca28ee41e3465228c45d84cc Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 7 Apr 2025 23:25:27 -0700 Subject: [PATCH 12/15] Fine-tuning code. --- MerlinAU.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index f8efd2f1..329a7581 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -10829,6 +10829,8 @@ then inMenuMode=true _DoInitializationStartup_ + _CheckFor_VersionFile_ + if _AcquireLock_ cliFileLock then _CheckForNewScriptUpdates_ @@ -10839,7 +10841,6 @@ then _ConfirmCronJobForFWAutoUpdates_ _CheckFor_WebGUI_Page_ - _CheckFor_VersionFile_ _MainMenu_ "$@" _DoExit_ 0 From 287e7a5c816c8082b31a9c1ac7ec7bad6a7470fa Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Tue, 8 Apr 2025 03:08:57 -0400 Subject: [PATCH 13/15] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e23e13b1..604c89fb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MerlinAU - AsusWRT-Merlin Firmware Auto Updater ## v1.4.1 -## 2025-Apr-07 +## 2025-Apr-08 ## WebUI: ![image](https://github.com/user-attachments/assets/92701007-a902-4724-9bae-b255856a686a) From 8d44cf149a6ce56b6cf5d638d8f92f0a0f3951e0 Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Tue, 8 Apr 2025 05:45:15 -0400 Subject: [PATCH 14/15] Patch Update Process Patch Update Process --- MerlinAU.sh | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/MerlinAU.sh b/MerlinAU.sh index 329a7581..c678bfd0 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -4,7 +4,7 @@ # # Original Creation Date: 2023-Oct-01 by @ExtremeFiretop. # Official Co-Author: @Martinski W. - Date: 2023-Nov-01 -# Last Modified: 2025-Apr-07 +# Last Modified: 2025-Apr-08 ################################################################### set -u @@ -2806,9 +2806,9 @@ _DownloadScriptFiles_() return "$retCode" } -##----------------------------------------## -## Modified by Martinski W. [2025-Mar-24] ## -##----------------------------------------## +##------------------------------------------## +## Modified by ExtremeFiretop [2025-Apr-08] ## +##------------------------------------------## _SCRIPT_UPDATE_() { local extraParam="" @@ -2850,7 +2850,7 @@ _SCRIPT_UPDATE_() if "$mountWebGUI_OK" then _SetVersionSharedSettings_ server "$DLRepoVersion" ; fi - if [ "$SCRIPT_VERSION" = "$DLRepoVersion" ] + if [ "$SCRIPT_VERSION" = "$DLRepoVersion" ] && { [ -z "$DLRepoBuildNum" ] || [ "$DLRepoBuildNum" = "$ScriptBuildNum" ]; } then echo -e "${CYANct}You are on the latest version! Would you like to download anyways?${NOct}" echo -e "${CYANct}This will overwrite your currently installed version.${NOct}" @@ -2865,9 +2865,13 @@ _SCRIPT_UPDATE_() fi printf "\n${CYANct}Download successful!${NOct}\n" printf "$(date) - Successfully downloaded $SCRIPT_NAME v${DLRepoVersion}\n" + printf "${CYANct}Update successful! Restarting script...${NOct}\n" + sleep 1 + _CheckForNewGUIVersionUpdate_ && extraParam="install" + _ReleaseLock_ + exec "$ScriptFilePath" $extraParam + exit 0 fi - _WaitForEnterKey_ - return else printf "\n\n${GRNct}Exiting Script Update Utility...${NOct}\n" sleep 1 @@ -2875,6 +2879,9 @@ _SCRIPT_UPDATE_() fi elif [ "$scriptUpdateNotify" != "0" ] then + if [ -n "$DLRepoBuildNum" ] && [ "$DLRepoBuildNum" -gt "$ScriptBuildNum" ] + then echo -e "${CYANct}Developer update with timestamp $DLRepoBuildNum available!${NOct}" + fi echo -e "${CYANct}Bingo! New version available! Would you like to update now?${NOct}" if _WaitForYESorNO_ then @@ -2885,6 +2892,7 @@ _SCRIPT_UPDATE_() if "$mountWebGUI_OK" then _SetVersionSharedSettings_ local "$DLRepoVersion" fi + printf "\n${CYANct}Download successful!${NOct}\n" printf "\n$(date) - Successfully downloaded $SCRIPT_NAME v${DLRepoVersion}\n" printf "${CYANct}Update successful! Restarting script...${NOct}\n" sleep 1 From 3053b70a393eb923162bb2c9ae52e1a7a7d73b99 Mon Sep 17 00:00:00 2001 From: Joel Samson Date: Tue, 8 Apr 2025 05:52:04 -0400 Subject: [PATCH 15/15] Update version.txt --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index a8fd7c9b..9e0593f5 100644 --- a/version.txt +++ b/version.txt @@ -1,2 +1,2 @@ 1.4.1 -25040803 +25040806