diff --git a/.github/workflows/update-merlin-sha256.yml b/.github/workflows/update-merlin-sha256.yml new file mode 100644 index 00000000..7bf939be --- /dev/null +++ b/.github/workflows/update-merlin-sha256.yml @@ -0,0 +1,121 @@ +name: Update Merlin SHA256 Checksums + +on: + schedule: + # Every 15 minutes, offset from the top of the hour to reduce scheduler congestion. + - cron: '7,22,37,52 * * * *' + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: update-merlin-sha256 + cancel-in-progress: false + +jobs: + scrape-and-commit: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Checkout repository + uses: actions/checkout@v7 + with: + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Fetch, parse, and validate SHA256 signatures + shell: bash + run: | + set -euo pipefail + + readonly SOURCE_URL='https://www.asuswrt-merlin.net/download' + readonly TARGET_FILE='merlin-sha256.txt' + readonly MIN_EXPECTED_ENTRIES=5 + + page_file="$(mktemp)" + candidate_file="$(mktemp)" + trap 'rm -f "$page_file" "$candidate_file"' EXIT + + echo "Fetching SHA256 signatures from ${SOURCE_URL}..." + curl --fail --location --silent --show-error \ + --retry 4 --retry-delay 5 --retry-connrefused \ + --connect-timeout 15 --max-time 60 \ + --user-agent 'MerlinAutoUpdate checksum mirror (+https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router)' \ + --output "$page_file" \ + "$SOURCE_URL" + + # Keep the same source section MerlinAU consumes today, but write to a + # temporary candidate so a scrape/parser failure cannot destroy the + # last-known-good mirror in the repository. + sed -n '/<.*>SHA256 signatures:<\/.*>/,/<\/pre>/p' "$page_file" | \ + sed -n '/]*>/,/<\/pre>/p' | \ + sed -e 's/^.*]*>//' \ + -e 's/<[^>]*>//g' \ + -e 's/^[[:space:]]*//' \ + -e 's/[[:space:]]*$//' | \ + tr -d '\r' | \ + sed '/^[[:space:]]*$/d' > "$candidate_file" + + echo "Validating candidate checksum list..." + awk -v min_entries="$MIN_EXPECTED_ENTRIES" ' + BEGIN { + valid = 1 + count = 0 + } + { + count++ + + if (NF != 2) { + printf "Invalid field count on line %d: %s\n", NR, $0 > "/dev/stderr" + valid = 0 + next + } + + if (length($1) != 64 || $1 ~ /[^0-9A-Fa-f]/) { + printf "Invalid SHA256 on line %d: %s\n", NR, $1 > "/dev/stderr" + valid = 0 + } + + if (seen[$2]++) { + printf "Duplicate firmware filename on line %d: %s\n", NR, $2 > "/dev/stderr" + valid = 0 + } + } + END { + if (count < min_entries) { + printf "Only %d checksum entries were parsed; expected at least %d.\n", count, min_entries > "/dev/stderr" + valid = 0 + } + + if (!valid) + exit 1 + } + ' "$candidate_file" + + echo "Validated $(wc -l < "$candidate_file") checksum entries." + echo "Candidate preview:" + head -n 5 "$candidate_file" + + # Replace the working-tree copy only after the candidate has passed + # every validation check. A failed run therefore leaves the repository + # and its last-known-good checksum mirror unchanged. + mv -f "$candidate_file" "$TARGET_FILE" + + - name: Commit and push changes + shell: bash + run: | + set -euo pipefail + + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + + git add merlin-sha256.txt + + if git diff --cached --quiet; then + echo 'No checksum changes detected. Nothing to commit.' + exit 0 + fi + + git commit -m 'Automated update: refresh Merlin SHA256 checksums' + git push diff --git a/ADDITIONAL_TERMS.md b/ADDITIONAL_TERMS.md new file mode 100644 index 00000000..a73f985d --- /dev/null +++ b/ADDITIONAL_TERMS.md @@ -0,0 +1,178 @@ +# MerlinAU Additional Terms Under GNU GPLv3 Section 7 + +Effective date: [YYYY-MM-DD] + +The MerlinAU software is licensed under the GNU General Public License +version 3.0 ("GPLv3"). + +This document contains additional terms authorized under Section 7 of +GPLv3 for MerlinAU material whose copyright holders have authorized +these terms. + +These Additional Terms supplement, and do not replace, GPLv3. + +Nothing in these Additional Terms is intended to restrict the rights to +run, study, copy, modify, or redistribute the software that are granted +under GPLv3. + +## 1. Scope + +These Additional Terms apply to MerlinAU material for which the +applicable copyright holder or copyright holders have authorized their +application. + +They do not purport to impose additional terms on third-party material +for which the MerlinAU project does not have authority to impose such +terms. + +Contributions accepted after the effective date of these Additional +Terms may be distributed subject to these Additional Terms where the +contributor has agreed to them. + +## 2. Preservation of Attribution and Legal Notices + +Pursuant to Section 7(b) of GPLv3, reasonable legal notices and author +attributions contained in covered MerlinAU material must be preserved. + +This includes, where applicable, notices identifying: + +- ExtremeFiretop as the original creator of the MerlinAU project; +- Martinski W. as an official co-author of the MerlinAU project; +- the applicable copyright notices; +- the GNU General Public License version 3.0; +- these Additional Terms; and +- the official MerlinAU project source. + +The official MerlinAU project is: + +https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router + +These requirements do not prevent a modified version from adding +appropriate attribution for its own authors and contributors. + +## 3. Identification of Modified Versions + +Pursuant to Section 7(c) of GPLv3, a version of covered MerlinAU +material that has been modified and conveyed to others must be +reasonably identified as different from the official MerlinAU version +from which it was derived. + +A modified version must not misrepresent its origin or represent itself +as an unmodified official MerlinAU release. + +Where reasonably visible to users, the modified version must identify +that: + +1. it contains modifications to MerlinAU; +2. it is not an official MerlinAU release unless expressly authorized + as such by the MerlinAU project; and +3. the modifications were made by persons other than the maintainers of + the official MerlinAU release, where applicable. + +This requirement supplements the modified-version notice requirements +already contained in Section 5 of GPLv3. + +Nothing in this section prevents a derivative project from truthfully +describing itself as being based on, derived from, or forked from +MerlinAU. + +## 4. No Misrepresentation of Origin + +Pursuant to Section 7(c) of GPLv3, covered MerlinAU material may not be +conveyed in a manner that misrepresents the origin of that material. + +A person distributing a modified version must not falsely state or +imply that the modifications: + +- were created by the official MerlinAU project; +- were created by ExtremeFiretop; +- were created by Martinski W.; +- are maintained by the official MerlinAU project; or +- constitute an official MerlinAU release, + +unless such a statement is factually correct or the distributor has +received authorization to make it. + +## 5. Names of Authors and Maintainers + +Pursuant to Section 7(d) of GPLv3, the names, usernames, or identities +of MerlinAU authors, contributors, or licensors may not be used for +publicity or promotional purposes in a manner that falsely implies +their sponsorship, endorsement, or approval of a modified or derivative +version. + +This provision does not prohibit reasonable attribution or truthful +statements describing the origin or history of the software. + +## 6. Trademark Rights Are Not Granted + +Pursuant to Section 7(e) of GPLv3, no rights under trademark law are +granted by the GPLv3 license or by these Additional Terms for the use +of the following project marks: + +- MerlinAU™ +- MerlinAutoUpdate™ +- the official MerlinAU logo or logos +- other distinctive MerlinAU project branding + +Rights to copy, modify, and redistribute the underlying GPL-licensed +software are separate from rights that may exist in project names, +logos, and other trademarks. + +Refer to `TRADEMARKS.md` for the MerlinAU trademark-use policy. + +Nothing in this section is intended to prohibit uses of a mark that are +independently permitted by applicable trademark law, including +truthful use reasonably necessary to identify the origin of a +derivative work. + +## 7. Official Project + +For purposes of these Additional Terms, the official MerlinAU project +is the project maintained at: + +https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router + +A fork, clone, mirror, modified distribution, or derivative work does +not become an official MerlinAU release merely because it originates +from the official repository. + +Official status requires authorization from the person or persons +authorized to control the official MerlinAU project and its branding. + +## 8. Relationship to GPLv3 + +These Additional Terms are intended to fall only within the categories +permitted by Section 7 of GPLv3. + +They do not prohibit: + +- creating a fork; +- privately modifying MerlinAU; +- publicly distributing a modified version; +- changing MerlinAU functionality; +- removing or replacing MerlinAU functionality; or +- creating an independently maintained derivative, + +provided the applicable requirements of GPLv3 and valid Additional +Terms are followed. + +If any provision of this document would constitute a "further +restriction" prohibited by GPLv3 rather than a valid Section 7 +additional term, that provision is not intended to restrict rights +otherwise granted by GPLv3. + +## 9. Applicable Version + +These Additional Terms apply only to MerlinAU material released with a +notice stating that these Additional Terms apply. + +Earlier copies of MerlinAU received without these Additional Terms +remain governed by the licensing terms applicable to those copies. + +--- + +MerlinAU™ / MerlinAutoUpdate™ + +Official project: +https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 11cf677f..b88bba56 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,45 +1,138 @@ -**Contributing to MerlinAU** +# Contributing to MerlinAU -We're thrilled that you're interested in contributing to MerlinAU! -This document provides a set of guidelines for contributing to MerlinAU, which is hosted on Github here: [MerlinAU](https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router). -These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. +We're thrilled that you're interested in contributing to MerlinAU! -**Code of Conduct** -- This project and everyone participating in it are governed by the MerlinAU Code of Conduct. -By participating, you are expected to uphold this code. Please report unacceptable behavior to @ExtremeFiretop. +This document provides a set of guidelines for contributing to MerlinAU, which is hosted on GitHub here: [MerlinAU](https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router). -**License** -- MerlinAU is licensed under the GNU General Public License v3.0 (GPL-3.0), a free, copyleft license for software and other kinds of works, which ensures end users the freedom to run, study, share, and modify the software. +Most contribution workflow guidance in this document is advisory. However, the licensing, intellectual property, and Contributor Certification provisions describe terms applicable to contributions +submitted to the MerlinAU project. Use your best judgment regarding the contribution guidelines, and feel free to propose changes to this document in a pull request. -------------------------------------- -**How Can I Contribute?** +## Code of Conduct -**Reporting Bugs** -- Use a clear and descriptive title for the issue to identify the problem. -- Describe the exact steps which reproduce the problem in as much detail as possible. -- Provide specific examples screenshots or logs to demonstrate the steps +* This project and everyone participating in it are governed by the MerlinAU Code of Conduct. +* By participating, you are expected to uphold this code. +* Please report unacceptable behavior to @ExtremeFiretop. -**Suggesting Enhancements** -- Use a clear and descriptive title for the issue to identify the suggestion. -- Provide a step-by-step description of the suggested enhancement in as much detail as possible. +## Official Repository + +The official MerlinAU repository is: + +https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router + +## License and Licensing of Contributions + +MerlinAU is licensed under the GNU General Public License version 3.0 (GPL-3.0), a free copyleft license that ensures end users have the freedom to run, study, share, and modify the software. + +By intentionally submitting a contribution to the official MerlinAU project for inclusion in MerlinAU, you agree that your contribution may be distributed as part of MerlinAU under: + +1. the GNU General Public License version 3.0; and +2. the applicable additional terms described in [ADDITIONAL_TERMS.md](ADDITIONAL_TERMS.md). + +You represent that you have the right to submit your contribution under those terms. + +If your contribution contains material that you did not create, you must ensure that the material may legally be included in MerlinAU and must identify any applicable third-party copyright or license terms. + +Do not submit code copied from a source whose license is incompatible with GPLv3. + +## GPLv3 Section 7 Additional Terms + +MerlinAU uses certain additional terms permitted under Section 7 of GPLv3. + +These concern matters including: + +* preservation of reasonable legal and author notices; +* accurate identification of the origin of MerlinAU material; +* reasonable identification of modified versions; +* use of author or licensor names for publicity; and +* the absence of any grant of trademark rights in the MerlinAU marks. + +Read the complete terms here: + +**[ADDITIONAL_TERMS.md](ADDITIONAL_TERMS.md)** + +By intentionally submitting a contribution for inclusion in MerlinAU, you agree that the project may distribute that contribution subject to those applicable terms. + +## Trademarks + +The source-code license and the MerlinAU trademarks are separate. + +**MerlinAU™** and **MerlinAutoUpdate™** identify the official MerlinAU project. + +Contributing code to MerlinAU does not transfer ownership of the MerlinAU trademarks to the contributor and does not grant permission to use those marks as the primary branding of an independent derivative project. + +The trademark policy does not prevent contributors or derivative projects from truthfully identifying their relationship to MerlinAU where permitted by the policy and applicable law. + +See: + +**[TRADEMARKS.md](TRADEMARKS.md)** + +## Copyright + +Unless a separate written agreement provides otherwise, contributors retain whatever copyright they hold in their own contributions while licensing those contributions for distribution as described above. + +Submission of a contribution does not by itself transfer copyright ownership to the MerlinAU project or its maintainers. + +--- + +# How Can I Contribute? + +## Reporting Bugs + +* Use a clear and descriptive title for the issue to identify the problem. +* Describe the exact steps that reproduce the problem in as much detail as possible. +* Provide specific examples, screenshots, or logs to demonstrate the problem. + +## Suggesting Enhancements + +* Use a clear and descriptive title for the issue to identify the suggestion. +* Provide a step-by-step description of the suggested enhancement in as much detail as possible. + +## Your First Code Contribution + +Pull requests are the method for submitting changes. Here's the general process: -**Your First Code Contribution** -- Pull requests are the method for submitting changes. Here's the general process: 1. Fork the repository. -2. Create a new branch in your fork (git checkout -b feature/my-new-feature). +2. Create a new branch in your fork: + `git checkout -b feature/my-new-feature` 3. Make your changes. -4. Commit your changes (git commit -am 'Add some feature'). -5. Push to the branch (git push origin feature/my-new-feature). +4. Commit your changes: + `git commit -am 'Add some feature'` +5. Push to the branch: + `git push origin feature/my-new-feature` 6. Create a new Pull Request. -**Pull Request Guidelines** -- Write clear and concise commit messages. -- Include links to existing BUGS or REQs when possible. -- Include screenshots and logs whenever possible. -- End all files with a newline. +## Pull Request Guidelines + +* Write clear and concise commit messages. +* Include links to existing BUGs or REQs when possible. +* Include screenshots and logs whenever possible. +* Clearly describe the purpose of the change. +* Identify significant behavioral changes. +* Test the change where reasonably possible. +* Do not remove existing copyright, licensing, attribution, or project notices without a valid reason. +* Identify any third-party code or dependencies introduced by the change. +* Ensure that you have the right to submit the contribution under the project's licensing terms. +* End all files with a newline. + +## Contributor Certification + +By submitting a contribution to the official MerlinAU project, you +agree that your contribution may be distributed under GPLv3 and the +applicable MerlinAU Section 7 Additional Terms. + +You also certify, to the best of your knowledge, that: + +* you created the contribution or otherwise have the right to submit it; +* you understand that the contribution will be publicly distributed; +* you have identified any third-party material included in the + contribution and its applicable licensing requirements; and +* you understand that contributing to MerlinAU does not make an + independently maintained derivative an official MerlinAU project. + +## Documentation Styleguide + +* Keep language simple and clear. -**Documentation Styleguide** -- Keep language simple and clear. +## More Questions? -**More Questions?** -- Feel free to ask for help if you need it, either via issues or through the provided contact owner @ExtremeFiretop. +Feel free to ask for help if you need it, either through issues or by contacting the project owner, @ExtremeFiretop. diff --git a/MerlinAU.asp b/MerlinAU.asp index e895c427..ec4b2d66 100644 --- a/MerlinAU.asp +++ b/MerlinAU.asp @@ -1,3 +1,21 @@ + + diff --git a/MerlinAU.sh b/MerlinAU.sh index 6237db63..531b3793 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -1,19 +1,29 @@ #!/bin/sh -################################################################### +############################################################################## # MerlinAU.sh (MerlinAutoUpdate) # -# Original Creation Date: 2023-Oct-01 by @ExtremeFiretop. -# Official Co-Author: @Martinski W. - Date: 2023-Nov-01 -# Last Modified: 2026-Aug-16 -################################################################### +# Project Created: 2023-Oct-01 by @ExtremeFiretop +# Official Co-Author: @Martinski W. since 2023-Nov-01 +# Last Modified: 2026-Sep-03 +# +# MerlinAU™ / MerlinAutoUpdate™ +# Official project: https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router +# +# Licensed under the GNU General Public License v3.0. +# Additional terms under GPLv3 Section 7 apply to covered material. +# See ADDITIONAL_TERMS.md. +# +# MerlinAU™ and MerlinAutoUpdate™ are project trademarks. +# The GPLv3 license does not grant trademark rights. See TRADEMARKS.md. +############################################################################## set -u ## Set version for each Production Release ## -readonly SCRIPT_VERSION=1.6.6 -readonly SCRIPT_VERSTAG="26081603" +readonly SCRIPT_VERSION=1.6.7 +readonly SCRIPT_VERSTAG="26090309" readonly SCRIPT_NAME="MerlinAU" ## Set to "master" for Production Releases ## -SCRIPT_BRANCH="master" +SCRIPT_BRANCH="dev" ##----------------------------------------## ## Modified by Martinski W. [2024-Jul-03] ## @@ -26,6 +36,9 @@ SCRIPT_URL_REPO="${SCRIPT_URL_BASE}/$SCRIPT_BRANCH" 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" +readonly FW_SHA256_URL="https://www.asuswrt-merlin.net/download" +# The scheduled checksum mirror is maintained on the repository's default branch # +readonly FW_SHA256_MIRROR_URL="${SCRIPT_URL_BASE}/main/merlin-sha256.txt" ##----------------------------------------## ## Modified by Martinski W. [2024-May-31] ## @@ -90,6 +103,7 @@ readonly versionDev_TAG="${SCRIPT_VERSION}_${SCRIPT_VERSTAG}" ##----------------------------------------## ## Modified by Martinski W. [2025-Jan-15] ## ##----------------------------------------## +readonly TEMP_DIR="/tmp/var/tmp" readonly ADDONS_PATH="/jffs/addons" readonly SCRIPTS_PATH="/jffs/scripts" readonly SETTINGS_DIR="${ADDONS_PATH}/$ScriptDirNameD" @@ -111,6 +125,9 @@ 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\"\}," +readonly curlHTTPstatusStr="HTTP/S_Status_Code" +readonly curlTmpLogFile="${TEMP_DIR}/tmpCurl_${ScriptFNameTag}_$$.TMP.LOG" +readonly curlErrLogFile="${TEMP_DIR}/tmpCurl_${ScriptFNameTag}_$$.ERR.LOG" # Give FIRST priority to built-in binaries over any other # export PATH="/bin:/usr/bin:/sbin:/usr/sbin:$PATH" @@ -156,9 +173,9 @@ 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 tempEMailContent="${TEMP_DIR}/tempEMailContent.$$.TXT" +readonly tempEMailBodyMsg="${TEMP_DIR}/tempEMailBodyMsg.$$.TXT" +readonly tempNodeEMailList="${TEMP_DIR}/tempNodeEMailList.$$.TXT" readonly saveEMailInfoMsg="${SETTINGS_DIR}/savedEMailInfoMsg.SAVE.TXT" readonly theEMailDateTimeFormat="%Y-%b-%d %a %I:%M:%S %p %Z" @@ -343,7 +360,7 @@ _UserLogMsg_() DoPrintf() { if "$isInteractive" && "$isVerbose" - then printf "$@" + then printf "$1" fi } @@ -580,9 +597,9 @@ _ReleaseMutexFLock_() [ "$fwupMutexFLock_OK" != "true" ] then return 0 fi - printf '' > "$fwupMutexFLock_FN" flock -u "$fwupMutexFLock_FD" 2>/dev/null + eval exec "${fwupMutexFLock_FD}>&-" fwupMutexFLock_OK=false } @@ -618,9 +635,7 @@ _AcquireMutexFLock_() fi fi - [ ! -s "$fwupMutexFLock_FN" ] && \ eval exec "$fwupMutexFLock_FD>$fwupMutexFLock_FN" - if flock -x -n "$fwupMutexFLock_FD" 2>/dev/null then printf "$(basename "$0")|$$\n" > "$fwupMutexFLock_FN" @@ -2904,18 +2919,26 @@ _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" + local srceFilePathURL="${SCRIPT_URL_REPO}/$1" + local curlRetCode returnCODE statusSTRx httpStatusSTR - curl -LSs --retry 4 --retry-delay 5 --retry-connrefused \ - "$srceFilePathDL" -o "$tempFilePathDL" - if [ $? -ne 0 ] || [ ! -s "$tempFilePathDL" ] || \ - grep -iq "^404: Not Found" "$tempFilePathDL" + rm -f "$tempFilePathDL" + printf '' > "$curlErrLogFile" ; printf '' > "$curlTmpLogFile" + + curl -LSs --retry 3 --retry-delay 5 --retry-connrefused \ + --connect-timeout 30 --max-time 60 \ + -w "${curlHTTPstatusStr}: %{http_code}\n" --stderr "$curlErrLogFile" \ + "$srceFilePathURL" --output "$tempFilePathDL" >> "$curlTmpLogFile" + curlRetCode="$?" + + returnCODE="$curlRetCode" + statusSTRx="Curl Status Code: $curlRetCode" + httpStatusSTR="$(grep -oE "${curlHTTPstatusStr}: [4-5][0-9]{2,}" "$curlTmpLogFile")" + + if [ "$curlRetCode" -eq 0 ] && \ + [ -z "$httpStatusSTR" ] && [ -s "$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 @@ -2924,13 +2947,24 @@ _CurlFileDownload_() fi if ! mv -f "$tempFilePathDL" "$2" then + returnCODE=111 rm -f "$tempFilePathDL" - return 1 fi - retCode=0 + else + if [ "$curlRetCode" -eq 0 ] && [ -n "$httpStatusSTR" ] + then + returnCODE="$(echo "$httpStatusSTR" | awk -F' ' '{print $2}')" + statusSTRx="HTTP/S Status Code: $returnCODE" + fi + if [ -s "$curlErrLogFile" ] && "$isInteractive" + then echo ; cat "$curlErrLogFile" + fi + Say "${REDct}**ERROR**${NOct}: Unable to download the file [$2] [${MGNTct}${statusSTRx}${NOct}]" + rm -f "$tempFilePathDL" fi - return "$retCode" + rm -f "$curlErrLogFile" "$curlTmpLogFile" + return "$returnCODE" } ##----------------------------------------## @@ -2953,9 +2987,12 @@ _DownloadScriptFiles_() 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 + retCode=0 + dos2unix "$SCRIPT_WEB_ASP_PATH" chmod 664 "$SCRIPT_WEB_ASP_PATH" if "$updatedWebUIPage" then @@ -2968,15 +3005,17 @@ _DownloadScriptFiles_() 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" + retCode=0 + dos2unix "$ScriptFilePath" + chmod 755 "$ScriptFilePath" else retCode=1 Say "${REDct}**ERROR**${NOct}: Unable to download latest script file for $SCRIPT_NAME." @@ -3085,7 +3124,7 @@ _SCRIPT_UPDATE_() if ! _CheckNewScriptMinFWBeforeUpdate_ then _WriteVarDefToHelperJSFile_ "minimumScriptFWRequired" "$NewMinSupportedFirmwareVers" - printf "\n${CRITct}*WARNING*:${NOct} MerlinAU v${DLRepoVersion} " + printf "\n${CRITct}*WARNING*${NOct}: MerlinAU v${DLRepoVersion} " printf "requires a newer router firmware version.\n" printf "\nCurrent F/W version found: ${REDct}%s${NOct}" "$current_version" printf "\nMinimum version supported: ${GRNct}%s${NOct}\n" "$NewMinSupportedFirmwareVers" @@ -3159,7 +3198,7 @@ _SCRIPT_UPDATE_() if ! _CheckNewScriptMinFWBeforeUpdate_ then _WriteVarDefToHelperJSFile_ "minimumScriptFWRequired" "$NewMinSupportedFirmwareVers" - printf "\n${CRITct}*WARNING*:${NOct} MerlinAU v${DLRepoVersion} " + printf "\n${CRITct}*WARNING*${NOct}: MerlinAU v${DLRepoVersion} " printf "requires a newer router firmware version.\n" printf "\nCurrent F/W version found: ${REDct}%s${NOct}" "$current_version" printf "\nMinimum version supported: ${GRNct}%s${NOct}\n" "$NewMinSupportedFirmwareVers" @@ -3258,7 +3297,7 @@ ScriptUpdateFromAMTM() ##----------------------------------------## _CheckForNewScriptUpdates_() { - local verStr DLScriptVerPath="${SCRIPT_VERPATH}.DL.tmp" + local verStr DLScriptVerPath="${SCRIPT_VERPATH}.DL.TMP" echo DLRepoVersion="$SCRIPT_VERSION" if [ -s "$SCRIPT_VERPATH" ] @@ -4896,7 +4935,7 @@ _GetPasswordInput_() local newPSWDtmpStr PSWDprompt showPSWD local retCode charNum newPSWDlength # For more responsive TAB keypress debounce # - local tabKeyDebounceSem="/tmp/var/tmp/${ScriptFNameTag}_TabKeySEM.txt" + local tabKeyDebounceSem="${TEMP_DIR}/${ScriptFNameTag}_TabKeySEM.txt" if [ $# -eq 0 ] || [ -z "$1" ] then @@ -5845,7 +5884,6 @@ _DownloadForMerlin_() wget --tries=5 --waitretry=5 --retry-connrefused \ -O "$FW_ZIP_FPATH" "$release_link" - # Check if the file was downloaded successfully # if [ ! -s "$FW_ZIP_FPATH" ] then return 1 else return 0 @@ -5944,7 +5982,7 @@ _CopyGnutonFiles_() if "$copy_attempted" && "$copy_success" then #---------------------------------------------------------------# - # Check if Gntuon file was downloaded to a USB-attached drive. + # Check if Gnuton file was downloaded to a USB-attached drive. # Take into account special case for Entware "/opt/" paths. #---------------------------------------------------------------# if ! echo "$FW_DL_FPATH" | grep -qE "^(/tmp/mnt/|/tmp/opt/|/opt/)" @@ -5971,45 +6009,156 @@ _CopyGnutonFiles_() return 0 } +##------------------------------------------## +## Modified by ExtremeFiretop [2026-Aug-24] ## +##------------------------------------------## +_GetFirmwareSHA256FromList_() +{ + local checksumList="$1" + local firmwareName="$2" + + #-------------------------------------------------------------------# + # Return a checksum ONLY when there is exactly one filename match + # and its digest is a valid SHA256 value. Using awk avoids + # treating the firmware image filenames as regular expressions. + #-------------------------------------------------------------------# + printf '%s\n' "$checksumList" | awk -v firmwareName="$firmwareName" ' + $2 == firmwareName && length($1) == 64 && $1 !~ /[^0-9A-Fa-f]/ { + matchCount++ + checksum = tolower($1) + } + END { + if (matchCount == 1) + print checksum + }' +} + +##-------------------------------------## +## Added by Martinski W. [2026-Sep-03] ## +##-------------------------------------## +_GetChecksumsFromRMerlinWebsite_() +{ + local curlRetCode returnCODE statusSTRx httpStatusSTR + local outTempFPathDL="${TEMP_DIR}/SHA256_SIGS_DL_$$.TMP" + + theChecksums="" + rm -f "$outTempFPathDL" + printf '' > "$curlErrLogFile" ; printf '' > "$curlTmpLogFile" + + curl -LSs --retry 3 --retry-delay 5 --retry-connrefused \ + --connect-timeout 30 --max-time 60 \ + -w "${curlHTTPstatusStr}: %{http_code}\n" --stderr "$curlErrLogFile" \ + "$FW_SHA256_URL" --output "$outTempFPathDL" >> "$curlTmpLogFile" + curlRetCode="$?" + + returnCODE="$curlRetCode" + statusSTRx="Curl Status Code: $curlRetCode" + httpStatusSTR="$(grep -oE "${curlHTTPstatusStr}: [4-5][0-9]{2,}" "$curlTmpLogFile")" + + if [ "$curlRetCode" -eq 0 ] && \ + [ -z "$httpStatusSTR" ] && [ -s "$outTempFPathDL" ] + then + theChecksums="$(cat "$outTempFPathDL" | \ + sed -n '/<.*>SHA256 signatures:<\/.*>/,/<\/pre>/p' | \ + sed -n '/]*>/,/<\/pre>/p' | \ + sed -e 's/^.*]*>// ; s/<[^>]*>//g' | \ + sed -e 's/^[[:space:]]*//g' | \ + sed -e 's/[[:space:]]*$//g' | \ + sed -e '/^[[:space:]]*$/d' | tr -d '\r')" + else + if [ "$curlRetCode" -eq 0 ] && [ -n "$httpStatusSTR" ] + then + returnCODE="$(echo "$httpStatusSTR" | awk -F' ' '{print $2}')" + statusSTRx="HTTP/S Status Code: $returnCODE" + fi + if [ -s "$curlErrLogFile" ] && "$isInteractive" + then echo ; cat "$curlErrLogFile" + fi + Say "${MGNTct}*WARNING*${NOct}: Unable to download the SHA256 checksum signature list from the ASUSWRT-Merlin website [${MGNTct}${statusSTRx}${NOct}]" + fi + + rm -f "$curlErrLogFile" "$curlTmpLogFile" "$outTempFPathDL" + return "$returnCODE" +} + ##----------------------------------------## -## Modified by Martinski W. [2025-Feb-17] ## +## Modified by Martinski W. [2026-Sep-03] ## ##----------------------------------------## _CheckOnlineFirmwareSHA256_() { - # Fetch the latest SHA256 checksums from ASUSWRT-Merlin website # - checksums="$(curl -Ls --retry 4 --retry-delay 5 --retry-connrefused \ - https://www.asuswrt-merlin.net/download | - sed -n '/<.*>SHA256 signatures:<\/.*>/,/<\/pre>/p' | - sed -n '/].*>/,/<\/pre>/p' | - sed -e 's/<[^>].*>//g; s/^[[:space:]]*//; s/[[:space:]]*$//')" + local fw_name fw_sig dl_sig="" + local theChecksums="" checksumSource="" - if [ -z "$checksums" ] + if [ ! -f "$firmware_file" ] then - Say "${REDct}**ERROR**${NOct}: Could not download the firmware SHA256 signatures from the website." + Say "${REDct}**ERROR**${NOct}: Firmware image file NOT found!" _DoCleanUp_ 1 return 1 fi - if [ -f "$firmware_file" ] + fw_name="$(basename "$firmware_file")" + fw_sig="$(openssl sha256 "$firmware_file" | awk -F ' ' '{print tolower($2)}')" + + #-----------------------------------------------------------------------# + # PRIMARY SOURCE: Fetch directly from ASUSWRT-Merlin official website. + # RMerlin's website host has a tendency to ban whole countries from + # accessing the server so we'll do more error checking & reporting + # to show when that happens so users become aware of the situation. + #-----------------------------------------------------------------------# + _GetChecksumsFromRMerlinWebsite_ + + if [ -n "$theChecksums" ] then - fw_sig="$(openssl sha256 "$firmware_file" | awk -F ' ' '{print $2}')" - # Extract the corresponding signature for the firmware file from the fetched checksums # - dl_sig="$(echo "$checksums" | grep "$(basename "$firmware_file")" | awk -F ' ' '{print $1}')" - if [ "$fw_sig" != "$dl_sig" ] + dl_sig="$(_GetFirmwareSHA256FromList_ "$theChecksums" "$fw_name")" + fi + + if [ -n "$dl_sig" ] + then + checksumSource="ASUSWRT-Merlin website" + else + Say "${MGNTct}*WARNING*${NOct}: Independently published checksum signature could NOT be retrieved from the ASUSWRT-Merlin website." + + #-----------------------------------------------------------------------# + # SECONDARY SOURCE: Use the repository mirror ONLY when the official + # source did NOT yield a usable checksum. Never use a checksum bundled + # with the firmware image in the ZIP archive for an online F/W update. + #-----------------------------------------------------------------------# + theChecksums="$(curl -Lfs --retry 3 --retry-delay 5 --retry-connrefused \ + --connect-timeout 30 --max-time 60 \ + "$FW_SHA256_MIRROR_URL" 2>/dev/null)" + + if [ -n "$theChecksums" ] + then + dl_sig="$(_GetFirmwareSHA256FromList_ "$theChecksums" "$fw_name")" + fi + + if [ -z "$dl_sig" ] then - Say "${REDct}**ERROR**${NOct}: SHA256 signature from extracted firmware file does not match the SHA256 signature from the website." + Say "${REDct}**ERROR**${NOct}: No unique and valid SHA256 checksum signature for ${fw_name} was available from either independent online source." + Say "Online firmware update was aborted. Bundled archive checksum fallback is intentionally disabled." _DoCleanUp_ 1 _SendEMailNotification_ FAILED_FW_CHECKSUM_STATUS return 1 - else - Say "SHA256 signature check for firmware image file passed successfully." - return 0 fi - else - Say "${REDct}**ERROR**${NOct}: Firmware image file NOT found!" + + checksumSource="MerlinAU GitHub repository mirror" + Say "${MGNTct}*WARNING*${NOct}: Using the MerlinAU GitHub checksum mirror for verification (15-MINUTE Update Intervals!)" + fi + + #--------------------------------------------------------------------------# + # If the PRIMARY source supplied a checksum but it's a mismatch, it fails + # immediately. The mirror must NOT be used to bypass a checksum mismatch. + #--------------------------------------------------------------------------# + if [ "$fw_sig" != "$dl_sig" ] + then + Say "${REDct}**ERROR**${NOct}: SHA256 signature from extracted firmware file does NOT match the SHA256 signature from the ${checksumSource}." _DoCleanUp_ 1 + _SendEMailNotification_ FAILED_FW_CHECKSUM_STATUS return 1 fi + + Say "SHA256 signature check for firmware image file passed successfully [source: ${checksumSource}]" + return 0 } ##----------------------------------------## @@ -6343,7 +6492,7 @@ _Approve_FW_Update_() if [ "$currentSetting" = "BLOCKED" ] then - printf "${REDct}*WARNING*:${NOct} Found high-risk phrases in the changelog file.\n" + printf "${REDct}*WARNING*${NOct}: Found high-risk phrases in the changelog file.\n" printf "The advice is to approve if you've read the firmware changelog and you want to proceed with the update.\n" if _WaitForYESorNO_ "Do you want to ${GRNct}APPROVE${NOct} the latest firmware update?" @@ -6355,7 +6504,7 @@ _Approve_FW_Update_() printf "The latest firmware update remain ${REDct}BLOCKED.${NOct}\n" fi else - printf "${REDct}*WARNING*:${NOct} Found high-risk phrases in the changelog file.\n" + printf "${REDct}*WARNING*${NOct}: Found high-risk phrases in the changelog file.\n" if _WaitForYESorNO_ "Do you want to ${REDct}BLOCK${NOct} the latest firmware update?" then Update_Custom_Settings "FW_New_Update_Changelog_Approval" "BLOCKED" @@ -9078,7 +9227,7 @@ _GetOfflineFirmwareVersion_() then fwVersionFormat="${BLUEct}BASE${WHITEct}.${CYANct}MAJOR${WHITEct}.${MGNTct}MINOR${WHITEct}.${YLWct}PATCH${NOct}" # Prompt user for the firmware version if extraction fails # - printf "\n${REDct}**WARNING**${NOct}\n" + printf "\n${REDct}*WARNING*${NOct}\n" if "$isGNUtonFW" then printf "\nFailed to identify firmware version from the update file name." @@ -9101,7 +9250,7 @@ _GetOfflineFirmwareVersion_() then return 1 fi - printf "\n${REDct}**WARNING**${NOct} Invalid format detected!\n" + printf "\n${REDct}*WARNING*${NOct}: Invalid format detected!\n" printf "\nPlease enter the firmware version number in the format ${fwVersionFormat}\n" if "$isGNUtonFW" then @@ -9623,7 +9772,7 @@ _RunFirmwareUpdateNow_() # it has the minimum firmware version supported. if "$routerModelCheckFailed" then - Say "${REDct}*WARNING*:${NOct} The current router model is not supported by this script." + Say "${REDct}*WARNING*${NOct}: The current router model is not supported by this script." if "$inMenuMode" then printf "\nWould you like to uninstall the script now?" @@ -9643,7 +9792,7 @@ _RunFirmwareUpdateNow_() fi if "$MinFirmwareVerCheckFailed" && ! "$offlineUpdateTrigger" then - Say "${REDct}*WARNING*:${NOct} The current firmware version is below the minimum supported. + Say "${REDct}*WARNING*${NOct}: The current firmware version is below the minimum supported. Please manually update to version ${GRNct}${MinSupportedFirmwareVers}${NOct} or higher to use this script.\n" "$inMenuMode" && _WaitForEnterKey_ "$theMenuReturnPromptMsg" return 1 @@ -9747,16 +9896,16 @@ Please manually update to version ${GRNct}${MinSupportedFirmwareVers}${NOct} or # Use set to read the output of the function into variables # if "$isGNUtonFW" then - Say "Using release information for Gnuton Firmware." - _GnutonBuildSelection_ - md5_url="$(GetLatestFirmwareMD5URL "$FW_GITURL_RELEASE" "$firmware_choice")" - GnutonChangeLogURL="$(GetLatestChangelogURL "$FW_GITURL_RELEASE")" - set -- $(_GetLatestFWUpdateVersionFromGitHub_ "$FW_GITURL_RELEASE" "$firmware_choice") - retCode="$?" + Say "Using release information for Gnuton Firmware." + _GnutonBuildSelection_ + md5_url="$(GetLatestFirmwareMD5URL "$FW_GITURL_RELEASE" "$firmware_choice")" + GnutonChangeLogURL="$(GetLatestChangelogURL "$FW_GITURL_RELEASE")" + set -- $(_GetLatestFWUpdateVersionFromGitHub_ "$FW_GITURL_RELEASE" "$firmware_choice") + retCode="$?" else - Say "Using release information for Merlin Firmware." - set -- $(_GetLatestFWUpdateVersionFromWebsite_ "$FW_SFURL_RELEASE") - retCode="$?" + Say "Using release information for Merlin Firmware." + set -- $(_GetLatestFWUpdateVersionFromWebsite_ "$FW_SFURL_RELEASE") + retCode="$?" fi if [ "$retCode" -eq 0 ] && [ $# -eq 2 ] && \ [ "$1" != "**ERROR**" ] && [ "$2" != "**NO_URL**" ] @@ -9781,7 +9930,7 @@ Please manually update to version ${GRNct}${MinSupportedFirmwareVers}${NOct} or NewUpdate_VersionVerify="$(_GetLatestFWUpdateVersionFromRouter_ 1)" if [ "$NewUpdate_VersionVerify" != "$release_version" ] then - Say "WARNING: The release version found by MerlinAU [$release_version] does not match the F/W update version from the router [$NewUpdate_VersionVerify]." + Say "*WARNING*: The release version found by MerlinAU [$release_version] does NOT match the F/W update version from the router [$NewUpdate_VersionVerify]." "$inMenuMode" && _WaitForEnterKey_ "$mainMenuReturnPromptStr" return 1 fi @@ -10175,8 +10324,8 @@ Please manually update to version ${GRNct}${MinSupportedFirmwareVers}${NOct} or #----------------------------------------------------------------------------------# # **IMPORTANT NOTE**: - # Due to the nature of 'nohup' and the specific behavior of this 'curl' request, - # the following 'curl' command MUST always be the last step in this block. + # Due to the nature of 'nohup' and the specific behavior of this 'Curl' request, + # the following 'Curl' command MUST always be the last step in this block. # Do NOT insert any commands after it! (unless you understand the implications). #----------------------------------------------------------------------------------# nohup curl -k "${routerURL}/upgrade.cgi" \ @@ -10197,9 +10346,9 @@ Please manually update to version ${GRNct}${MinSupportedFirmwareVers}${NOct} or #----------------------------------------------------------# # In the rare case that the F/W Update gets "stuck" for - # some reason & the "curl" cmd never returns, we create + # some reason & the "Curl" cmd never returns, we create # a background child process that sleeps for 3 minutes - # and then kills the "curl" process if it still exists. + # and then kills the "Curl" process if it still exists. # Otherwise, this child process does nothing & returns. # NORMALLY the "Curl" command returns almost instantly # once the upload is complete. @@ -10371,9 +10520,9 @@ _DelFWAutoUpdateHook_() fi } -##----------------------------------------## -## Modified by Martinski W. [2024-May-17] ## -##----------------------------------------## +##------------------------------------------## +## Modified by ExtremeFiretop [2026-Aug-24] ## +##------------------------------------------## _AddFWAutoUpdateHook_() { local hookScriptFile jobHookAdded=false @@ -10398,12 +10547,12 @@ _AddFWAutoUpdateHook_() if "$jobHookAdded" then Say "Cron job hook was added successfully to '$hookScriptFile' script." - else Say "Cron job hook already exists in '$hookScriptFile' script." + else DoPrintf "Cron job hook already exists in '$hookScriptFile' script.\n" fi } ##------------------------------------------## -## Modified by ExtremeFiretop [2024-Nov-18] ## +## Modified by ExtremeFiretop [2026-Aug-24] ## ##------------------------------------------## _AddScriptAutoUpdateHook_() { @@ -10429,7 +10578,7 @@ _AddScriptAutoUpdateHook_() if "$jobHookAdded" then Say "Cron job hook was added successfully to '$hookScriptFile' script." - else Say "Cron job hook already exists in '$hookScriptFile' script." + else DoPrintf "Cron job hook already exists in '$hookScriptFile' script.\n" fi } @@ -10465,25 +10614,25 @@ _CheckForMinimumRequirements_() if [ "$(uname -o)" != "ASUSWRT-Merlin" ] then requirementsCheckOK=false - Say "\n${CRITct}*WARNING*:${NOct} The current firmware installed is NOT ASUSWRT-Merlin.\n" + Say "\n${CRITct}*WARNING*${NOct}: The current firmware installed is NOT ASUSWRT-Merlin.\n" fi if ! nvram get rc_support | grep -qwoF "am_addons" then requirementsCheckOK=false - Say "\n${CRITct}*WARNING*:${NOct} The current firmware installed does NOT support add-ons.\n" + Say "\n${CRITct}*WARNING*${NOct}: The current firmware installed does NOT support add-ons.\n" fi if ! _CheckForMinimumModelSupport_ then requirementsCheckOK=false - Say "\n${CRITct}*WARNING*:${NOct} The current router model ${REDct}${FW_RouterModelID}${NOct} is NOT supported by this script.\n" + Say "\n${CRITct}*WARNING*${NOct}: The current router model ${REDct}${FW_RouterModelID}${NOct} is NOT supported by this script.\n" fi if ! _CheckForMinimumVersionSupport_ then requirementsCheckOK=false - Say "\n${CRITct}*WARNING*:${NOct} The current firmware version is below the minimum supported by this script." + Say "\n${CRITct}*WARNING*${NOct}: The current firmware version is below the minimum supported by this script." printf "\nCurrent F/W version found: ${REDct}${FW_InstalledVersion}${NOct}" printf "\nMinimum version supported: ${GRNct}${MinSupportedFirmwareVers}${NOct}\n" fi @@ -11471,20 +11620,20 @@ _ShowMainMenuOptions_() # Unsupported Model Check # if "$routerModelCheckFailed" then - Say "${REDct}*WARNING*:${NOct} The current router model is not supported by this script. + Say "${REDct}*WARNING*${NOct}: The current router model is not supported by this script. Please uninstall." echo fi if "$MinFirmwareVerCheckFailed" then - Say "${REDct}*WARNING*:${NOct} The current firmware version is below the minimum supported. + Say "${REDct}*WARNING*${NOct}: The current firmware version is below the minimum supported. Please manually update to version ${GRNct}${MinSupportedFirmwareVers}${NOct} or higher to use this script." echo fi if ! _HasRouterMoreThan256MBtotalRAM_ && ! _ValidateUSBMountPoint_ "$FW_ZIP_BASE_DIR" then - Say "${REDct}*WARNING*:${NOct} Limited RAM detected (256MB). + Say "${REDct}*WARNING*${NOct}: Limited RAM detected (256MB). A USB drive is required for F/W updates." echo fi @@ -12218,7 +12367,7 @@ _RunLockedInitializationChecks_() if ! _CleanUpOldLogFiles_ then - Say "${YLWct}WARNING:${NOct} Unable to clean up old firmware-update log files." + Say "${YLWct}*WARNING*${NOct}: Unable to clean up old firmware-update log files." retCode=1 fi @@ -12226,7 +12375,7 @@ _RunLockedInitializationChecks_() checkWebsUpdateScriptForGnuton="$isGNUtonFW" if ! _Gnuton_Check_Webs_Update_Script_ then - Say "${YLWct}WARNING:${NOct} Unable to check or install the GNUton \"${FW_WebsUpdateFile}\" patch." + Say "${YLWct}*WARNING*${NOct}: Unable to check or install the GNUton \"${FW_WebsUpdateFile}\" patch." retCode=1 fi diff --git a/README.md b/README.md index 3df3be2c..1492a294 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # MerlinAU - AsusWRT-Merlin Firmware Auto Updater -## v1.6.6 -## 2026-Aug-16 +## v1.6.7 +## 2026-Sep-03 ## WebUI: image @@ -87,6 +87,61 @@ Blocked due to being single image models. MerlinAU.sh is a versatile shell script designed to automate the firmware update process for ASUS routers running Asuswrt-Merlin firmware. It streamlines the firmware update procedure, automatically detects your router model, fetches the latest firmware, and offers options for installation. +## License, Official Project, and Trademarks + +MerlinAU is free and open-source software licensed under the +[GNU General Public License version 3.0](LICENSE). + +Official MerlinAU releases are maintained through this repository: + +**https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router** + +### Project Authors + +- **Project Creator:** @ExtremeFiretop — October 1, 2023 +- **Official Co-Author:** @Martinski W. — since November 1, 2023 + +### GPLv3 Additional Terms + +Certain MerlinAU material is also subject to additional terms permitted +under Section 7 of GPLv3, including requirements concerning attribution, +identification of modified versions, misrepresentation of origin, and +the absence of any grant of trademark rights. + +See: + +**[ADDITIONAL_TERMS.md](ADDITIONAL_TERMS.md)** + +### MerlinAU Trademarks + +**MerlinAU™** and **MerlinAutoUpdate™** identify the official MerlinAU +project. + +The GPLv3 license grants rights to copy, modify, and redistribute the +software. It does not grant ownership of the MerlinAU trademarks or an +unrestricted right to use MerlinAU branding for an independently +maintained derivative project. + +Forks and modified versions are permitted under the terms of GPLv3, but +they must not misrepresent themselves as official MerlinAU releases. + +A derivative project may truthfully identify itself as: + +> "Based on MerlinAU" + +or: + +> "An unofficial fork of MerlinAU" + +Use of names such as **MerlinAU Zero**, **MerlinAU Pro**, +**MerlinAutoUpdate Zero**, or similar names for an independently +branded derivative is not authorized under the MerlinAU trademark +policy without permission. + +See: + +**[TRADEMARKS.md](TRADEMARKS.md)** + ## NOTE: It is highly recommended to configure backups using BACKUPMON - https://github.com/ViktorJp/BACKUPMON/tree/main @@ -161,9 +216,9 @@ The script can be run using the below options: - (Cron calculator here: https://crontab.guru/) ## Contribution -- Before any contributions, please review: [CONTRIBUTING.md](https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router/blob/main/CONTRIBUTING.md) Guidelines. -- Also please review the: [CODE_OF_CONDUCT.md](https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router/blob/main/CODE_OF_CONDUCT.md). -- Feel free to contribute to this script by submitting issues or pull requests on GitHub. Your feedback and contributions are greatly appreciated! +- Before contributing, please review the [Contributing Guidelines](CONTRIBUTING.md). +- Please also review the [Code of Conduct](CODE_OF_CONDUCT.md). +- Feel free to contribute by submitting issues or pull requests. Your feedback and contributions are greatly appreciated! ## Use this Automatic F/W Update script at your own discretion. By using this script you assume all risks associated with updating a router to a new firmware version. diff --git a/TRADEMARKS.md b/TRADEMARKS.md new file mode 100644 index 00000000..9eef893f --- /dev/null +++ b/TRADEMARKS.md @@ -0,0 +1,261 @@ +# MerlinAU Trademark Policy + +Last updated: 2026-08-27 + +## 1. Purpose + +The MerlinAU source code is free and open-source software distributed +under the GNU General Public License version 3.0. + +The GPL grants broad rights to copy, modify, and redistribute the +software. + +Those copyright permissions are separate from rights associated with +the names, logos, and branding that identify the official MerlinAU +project. + +This policy explains how the MerlinAU project trademarks may be used. + +## 2. MerlinAU Marks + +The following names and branding are referred to in this policy as the +"MerlinAU Marks": + +- MerlinAU™ +- MerlinAutoUpdate™ +- the official MerlinAU logo +- distinctive logos or branding used to identify official MerlinAU + releases + +The MerlinAU Marks are claimed and controlled by: + +**Joel Samson, publicly known as @ExtremeFiretop** + +The use of the ™ symbol identifies an asserted trademark. It does not +represent that the mark is registered unless and until registration has +actually been obtained. + +## 3. Official Project + +The official and canonical MerlinAU project is: + +https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router + +Official MerlinAU releases are releases authorized through that project +or through another distribution channel expressly authorized by the +trademark owner. + +Merely forking, cloning, modifying, or redistributing MerlinAU does not +make a derivative version an official MerlinAU release. + +## 4. Official Co-Author and Licensed Use + +Martinski W. is an official co-author of MerlinAU and is authorized +to use the MerlinAU Marks in connection with his development, +documentation, support, promotion, and other authorized work on the +official MerlinAU project. + +Use of the MerlinAU Marks by Martinski W. in connection with the +official MerlinAU project is licensed by the trademark owner. + +The trademark owner retains direct or indirect control over the +character and quality of software and services distributed under the +MerlinAU Marks. + +This authorization and licensed use do not transfer ownership of the +MerlinAU Marks. + +## 5. Uses That Do Not Require Permission Under This Policy + +You may use the MerlinAU name reasonably and truthfully to identify the +original project or explain the origin of another project. + +Examples include: + +> FooUpdater is based on MerlinAU. + +> FooUpdater contains code derived from MerlinAU. + +> FooUpdater is an unofficial fork of MerlinAU. + +> Originally based on MerlinAU version 1.x. + +> Compatible with software originally developed by the MerlinAU +> project. + +You may also reproduce factual copyright and attribution notices that +identify MerlinAU, ExtremeFiretop, Martinski W., or the official +project. + +Nothing in this policy is intended to prohibit uses that applicable law +permits independently of permission from the trademark owner. + +## 6. Modified and Derivative Projects + +You may exercise all rights granted to you under GPLv3, including the +right to modify MerlinAU and distribute your modifications. + +However, permission is not granted under this trademark policy to use +the MerlinAU Marks as the primary identity or branding of an +independently maintained derivative project. + +A derivative should adopt a sufficiently distinct primary project name +and may then truthfully describe its relationship to MerlinAU. + +For example: + +### Permitted without additional trademark permission + +**ZeroUpdater** + +> An unofficial fork of MerlinAU. + +**RouterUpdateNG** + +> Based on the MerlinAU project. + +**AUPlus** + +> Derived from MerlinAU. + +### Not authorized under this policy as names for an independent +derivative + +- MerlinAU Zero +- MerlinAU-Zero +- MerlinAutoUpdate Zero +- MerlinAU Pro +- MerlinAU Plus +- MerlinAU NG +- MerlinAU Next +- MerlinAU Community Edition +- MerlinAU Enhanced +- MerlinAU Extended +- MerlinAutoUpdate Pro +- MerlinAutoUpdate NG + +The examples above are illustrative rather than exhaustive. + +Adding a word, suffix, prefix, version designation, or edition name to +a MerlinAU Mark does not by itself make the resulting branding +authorized under this policy. + +## 7. Official-Looking Branding + +Without permission, an independent derivative project should not use +the MerlinAU Marks in a manner that is likely to represent or imply +that the derivative is: + +- an official MerlinAU release; +- a new official edition of MerlinAU; +- the successor to the official MerlinAU project; +- sponsored by the MerlinAU project; +- maintained by the MerlinAU maintainers; or +- endorsed or approved by the MerlinAU project. + +Examples of branding that is not authorized under this policy include: + +> MerlinAU Zero — The Next Generation of MerlinAU + +> MerlinAU Pro — Official Enhanced Edition + +> MerlinAutoUpdate NG + +unless that use has been expressly authorized. + +## 8. Forks and Repository Names + +This policy does not prohibit use of normal source-control mechanisms +for creating or maintaining forks. + +A GitHub-generated fork that retains repository history or a repository +name associated with its upstream source should clearly identify +itself as a fork where appropriate and must not otherwise present +itself as the official MerlinAU repository. + +Permission is not granted to create an independently branded competing +project that incorporates MerlinAU or MerlinAutoUpdate into its primary +project, product, package, or repository identity in a manner that +suggests an official MerlinAU edition or successor. + +A distinct project name with a truthful statement such as: + +> Based on MerlinAU + +is preferred. + +## 9. Logos and Visual Branding + +The GPL license applicable to MerlinAU source code does not itself grant +trademark rights in the official MerlinAU logo or other distinctive +project branding. + +Unless permission has been granted, a modified or independently +maintained distribution should not use official MerlinAU logos or +visual branding as its own primary identity in a way that suggests it +is an official MerlinAU release. + +Reasonable reproduction for purposes such as attribution, historical +reference, commentary, screenshots, or explaining compatibility is not +intended to be prohibited by this policy where otherwise permitted by +law. + +## 10. Domain Names, Accounts, and Services + +Permission is not granted under this policy to register or use the +MerlinAU Marks in a domain name, social-media identity, service name, +or other identifier in a manner that falsely implies that the resource +is operated by or affiliated with the official MerlinAU project. + +Examples that would require permission include names presented as: + +- Official MerlinAU Support +- MerlinAU Official +- MerlinAU Pro +- MerlinAU Zero +- MerlinAutoUpdate Official + +Truthful references to the project remain permitted as described above. + +## 11. Attribution Is Not Endorsement + +The requirement to preserve copyright notices or acknowledge that code +originated from MerlinAU does not mean that the MerlinAU project, +ExtremeFiretop, or Martinski W. endorses the derivative work. + +Likewise, the ability to truthfully describe software as a "fork of +MerlinAU" does not make that software an official MerlinAU release. + +## 12. Permission + +Uses of the MerlinAU Marks that are not authorized by this policy may +be permitted with prior written authorization from the trademark owner. + +Permission may be subject to reasonable conditions intended to prevent +confusion regarding the source, quality, maintenance, or official +status of the software. + +## 13. Open-Source Rights Remain Intact + +This trademark policy does not modify the GNU GPLv3 copyright license +applicable to MerlinAU source code. + +Nothing in this policy is intended to prevent anyone from exercising +their rights under GPLv3 to: + +- copy MerlinAU; +- study MerlinAU; +- modify MerlinAU; +- create a fork; +- redistribute MerlinAU; or +- redistribute modified versions. + +The purpose of this policy is to distinguish those copyright freedoms +from use of the MerlinAU Marks as source-identifying branding. + +--- + +MerlinAU™ / MerlinAutoUpdate™ + +Official project: +https://github.com/ExtremeFiretop/MerlinAutoUpdate-Router diff --git a/merlin-sha256.txt b/merlin-sha256.txt new file mode 100644 index 00000000..2eed75ce --- /dev/null +++ b/merlin-sha256.txt @@ -0,0 +1,21 @@ +a04d65e566b70a2533f1dcde9e0e1e66133438268f66165caeb973a2aaa8e065 GT-AX11000_3004_388.12_2_rog_ubi.w +24f8679af3726386321aea8ae49af2e7a560f46a8f1fca5a93e31a31d72e43d2 GT-AX11000_3004_388.12_2_ubi.w +b78b365ec8060351c5143782ad9a438f67ab39f37b454fbe06113e99a62c6c25 GT-AXE11000_3004_388.12_2_pureubi.w +c4ef1675ecd772f381c6e5a696d643db89e28f64451d140f53bb8fea62d0089d GT-AXE11000_3004_388.12_2_rog_pureubi.w +352f4a89e86f02deb89d5569db0e354c89956f28225458f8e14f4fe6bacc2123 RT-AX58U_3004_388.12_2_puresqubi.w +936e04cccc6da05b94c19c3cb9c6d8b9fbb0a6542adc7b953aea3c0c7c068903 RT-AX68U_3004_388.12_2_pureubi.w +864cb94504bd0f036f730089c779aafbf5827721af10d5533924f94d3c20982a RT-AX86U_3004_388.12_2_pureubi.w +a902d77915c609cf5ee6ac6069c52e3ab460cd4b915f0febcb269175cc842a6d RT-AX88U_3004_388.12_2_ubi.w +5dc2284ac99bcb280b8f57c98d817ae17c1ae5e60102b8cb581680894739f467 GT-AX11000_PRO_3006_102.8_4_nand_squashfs.pkgtb +9497ab9a5956da9b6c9b86a1c0172e0eef9d8e02c9531598332f0a911a92e925 GT-AX6000_3006_102.8_4_nand_squashfs.pkgtb +ea266310a61dc9018fed850e1dba38b37335740fd5e0053683a1133d69837f4a GT-AXE16000_3006_102.8_4_nand_squashfs.pkgtb +f9e896c3b46a2913e60ea2ac638b4ca624d4d239b3a5416864da95f8b4ed1873 GT-BE19000AI_3006_102.8_4_emmc_squashfs.pkgtb +11932c048a9ecc2be8de93a19af985d685bb21999091d70a1b946fbfa57b7960 GT-BE98_PRO_3006_102.8_4_nand_squashfs.pkgtb +78f296e30bde73b842f3e211b3205bdab7e9b947f1b0b40d43a248cc86badaa7 RT-AX86U_PRO_3006_102.8_4_nand_squashfs.pkgtb +8eca0813db27ef8518535cd00060475c58c7928d8878e87d34df4476dde05550 RT-AX88U_PRO_3006_102.8_4_nand_squashfs.pkgtb +566bb3a9a6331293d7a28b2dbb0676dfa846a5f11bafa3a99c848b894c087606 RT-BE58_GO_3006_102.8_4_nand_squashfs.pkgtb +7cf298f161aca6de3ad4ff3840f08eae3c11a39c067da825e444439aac67dabc RT-BE86U_3006_102.8_4_nand_squashfs.pkgtb +28954e19157261fe97adcb266591de839c202d188d485484a87089149c61dea3 RT-BE88U_3006_102.8_4_nand_squashfs.pkgtb +1fc818b504f51a378fcbd1b8acde0d1e7950d28527c364cc8c4937c9a4072fbe RT-BE92U_3006_102.8_4_nand_squashfs.pkgtb +f4483a27071d4bc074b2e42760e736a8d079a5f0fb9cab1684553de11ce5f453 RT-BE96U_3006_102.8_4_nand_squashfs.pkgtb +12b00d614e5073e78c8e87ae84c688c2d93e7afcb4d0f36d479731b1cbb9f54e XT12_3006_102.8_4_nand_squashfs.pkgtb diff --git a/version.txt b/version.txt index ec70f755..400084b1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.6.6 +1.6.7