Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
efb382e
Merge pull request #473 from ExtremeFiretop/main
ExtremeFiretop May 17, 2025
470c596
Update MerlinAU.sh
ExtremeFiretop May 17, 2025
8bb8722
Patch WebUI Install Script Update Checkbox
ExtremeFiretop May 18, 2025
0cee781
Allow Changelog Firmware Migrations
ExtremeFiretop May 18, 2025
5afa1f6
No Block for Web Access Restrictions
ExtremeFiretop May 18, 2025
a790fb6
Adjust Script Version
ExtremeFiretop May 18, 2025
c6c3ed0
Update README.md
ExtremeFiretop May 19, 2025
81a080b
Update MerlinAU.sh
ExtremeFiretop May 19, 2025
cece920
Merge pull request #475 from ExtremeFiretop/Patch-WebUI
Martinski4GitHub May 19, 2025
40f8cdf
Fix Web Access Restrictions Regex
ExtremeFiretop May 19, 2025
f70169d
Add Missing Changelog Patch
ExtremeFiretop May 19, 2025
3c95762
Missing Comment Updates
ExtremeFiretop May 19, 2025
45a31d1
Actually Fix Web Access Restrictions
ExtremeFiretop May 19, 2025
fec2ac7
Update MerlinAU.sh
ExtremeFiretop May 20, 2025
7e9b05a
Update MerlinAU.sh
ExtremeFiretop May 20, 2025
4a1db6a
Update MerlinAU.sh
ExtremeFiretop May 20, 2025
7c52adb
Update MerlinAU.sh
ExtremeFiretop May 21, 2025
1cf1add
Update MerlinAU.sh
ExtremeFiretop May 21, 2025
a867960
Fix Changelog Verification
ExtremeFiretop May 21, 2025
5c141f5
Set Estimates to TBD when disabling
ExtremeFiretop May 21, 2025
1706ad2
Fix WebUI Estimations (Recalculations and TBD)
ExtremeFiretop May 22, 2025
e0e9fce
Bug Fix/Code Cleanup
ExtremeFiretop May 22, 2025
38a3721
Code cleanup
ExtremeFiretop May 22, 2025
cf1681f
Fix the Password Focus on Edge/Chrome
ExtremeFiretop May 23, 2025
34a76af
Commit missing comments
ExtremeFiretop May 23, 2025
a094ed7
Fix Memory Clearing for Low Memory Models
ExtremeFiretop May 28, 2025
8195634
Adding Back conn_diag
ExtremeFiretop May 29, 2025
96f29c6
Re-Implementing Memory Diff Solution
ExtremeFiretop May 29, 2025
11e41bb
Lowing Overhead - Removing Memory Subtraction Solution
ExtremeFiretop May 29, 2025
0629f93
Undoing Memory Based Changes
ExtremeFiretop May 31, 2025
d6075e1
Update README.md
ExtremeFiretop Jun 1, 2025
6ad695c
Merge pull request #476 from ExtremeFiretop/Fix-Web-Access-Restrictions
Martinski4GitHub Jun 1, 2025
bda5564
Fixes and Improvements
Martinski4GitHub Jun 1, 2025
d956d2a
Merge pull request #478 from Martinski4GitHub/dev
ExtremeFiretop Jun 1, 2025
4f0533b
Fixes and Improvements
Martinski4GitHub Jun 1, 2025
42d99ec
Merge pull request #479 from Martinski4GitHub/dev
ExtremeFiretop Jun 1, 2025
f29e73b
Modified RAM Requirements for F/W Flash Process
Martinski4GitHub Jun 2, 2025
3df2e77
Merge pull request #480 from Martinski4GitHub/dev
ExtremeFiretop Jun 3, 2025
bbc073c
Update README.md
ExtremeFiretop Jun 3, 2025
876ea47
Update README.md
ExtremeFiretop Jun 3, 2025
5c94966
Update README.md
ExtremeFiretop Jun 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 155 additions & 80 deletions MerlinAU.asp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<script language="JavaScript" type="text/javascript">

/**----------------------------**/
/** Last Modified: 2025-May-11 **/
/** Last Modified: 2025-Jun-01 **/
/**----------------------------**/

// Separate variables for shared and AJAX settings //
Expand Down Expand Up @@ -857,59 +857,91 @@ function FetchChangelog(startTime)
});
}

/**------------------------------------------**/
/** Modified by ExtremeFiretop [2025-May-18] **/
/**------------------------------------------**/
function ShowLatestChangelog(e)
{
if (e) e.preventDefault();

let loadingMessage = '<p>Please wait and allow up to 10 seconds for the changelog to load.<br>' +
'Click on "Cancel" button to stop and exit this dialog.</p>';
const loadingMessage =
'<p>Please wait and allow up to 10 seconds for the changelog to load.<br>' +
'Click on "Cancel" button to stop and exit this dialog.</p>';

if ($('#changelogModal').length)
/* ----- build the modal once ----- */
if (!$('#changelogModal').length)
{
$('#changelogData').html(loadingMessage);
$('#closeChangelogModal').text("Cancel");
}
else
{ // Create modal overlay if it doesn't exist //
$('body').append(
'<div id="changelogModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; ' +
'background:rgba(0,0,0,0.8); z-index:10000;">' +
'<div id="changelogContent" style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); ' +
'background:#fff; color:#000; padding:20px; max-height:90%; overflow:auto; width:80%; max-width:800px;">' +
'<h2 style="margin-top:0; color:#000;">Latest Changelog</h2>' +
'<button id="closeChangelogModal" style="float:right; font-size:14px; cursor:pointer;">Cancel</button>' +
'<div id="changelogData" style="font-family:monospace; white-space:pre-wrap; margin-top:10px; color:#000;">' +
'<div id="changelogModal" style="display:none;position:fixed;top:0;left:0;width:100%;height:100%;' +
'background:rgba(0,0,0,0.8);z-index:10000;">' +
'<div id="changelogContent" style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);' +
'background:#fff;color:#000;padding:20px;max-height:90%;overflow:auto;width:80%;max-width:800px;">' +
'<h2 style="margin-top:0;color:#000;">Latest Changelog</h2>' +
'<button id="closeChangelogModal" style="float:right;font-size:14px;cursor:pointer;">Cancel</button>' +
'<div id="changelogData" style="font-family:monospace;white-space:pre-wrap;margin-top:10px;color:#000;">' +
loadingMessage +
'</div>' +
'</div>' +
'</div>'
);
$('#closeChangelogModal').on('click', function(){

/* close button */
$('#closeChangelogModal').on('click', function () {
$('#changelogModal').hide();
});

/* ---------- NEW: arrow‑key scroll handler (bind once) ---------- */
$(document).on('keydown', function (ev) {
if (!$('#changelogModal').is(':visible')) { return; }
const box = $('#changelogContent')[0]; // the scrollable box //
switch (ev.key)
{
case 'ArrowDown':
box.scrollTop += 40;
ev.preventDefault();
break;
case 'ArrowUp':
box.scrollTop -= 40;
ev.preventDefault();
break;
case 'ArrowRight':
box.scrollTop += 40;
ev.preventDefault();
break;
case 'ArrowLeft':
box.scrollTop -= 40;
ev.preventDefault();
break;
default:
break;
}
});
/* -------------------------------------------------------------- */
}
else
{
$('#changelogData').html(loadingMessage);
$('#closeChangelogModal').text("Cancel");
}

$('#changelogModal').show();

// Trigger the backend shell script via form submission //
var formData = $('form[name="form"]').serializeArray();
/* ---------- NEW: focusable + give it focus ---------- */
$('#changelogContent').attr('tabindex', 0).focus();
/* ---------------------------------------------------- */

/* kick the backend */
const formData = $('form[name="form"]').serializeArray();
formData.push({ name: "action_script", value: "start_MerlinAUdownloadchangelog" });
formData.push({ name: "action_wait", value: "10" });

$.post('start_apply.htm', formData)
.done(function(response) {
console.log("Changelog trigger submitted successfully.");
})
.fail(function() {
console.error("Failed to submit changelog trigger.");
});

// Record the start time and wait 8 seconds before attempting to fetch the changelog //
var startTime = new Date().getTime();
setTimeout(function() {
FetchChangelog(startTime);
// Once the changelog has loaded, update the button text to "Close"
$('#closeChangelogModal').text("Close");
formData.push({ name: "action_wait", value: "10" });

$.post('start_apply.htm', formData);

/* wait 8s, then fetch the changelog */
const startTime = Date.now();
setTimeout(function () {
FetchChangelog(startTime);
$('#closeChangelogModal').text("Close");
}, 8000);

return false;
Expand Down Expand Up @@ -1034,14 +1066,14 @@ function GetExternalCheckResults()
}

/**----------------------------------------**/
/** Modified by Martinski W. [2025-Mar-07] **/
/** Modified by Martinski W. [2025-Jun-01] **/
/**----------------------------------------**/
// To support 'routerPassword' element //
const loginPassword =
{
minLen: 5, maxLen: 64, pswdLen: 0, pswdStr: '',
pswdInvalid: false, pswdVerified: false, pswdUnverified: false,
allBlankCharsRegExp: '^[ ]+$',
pswdFocus: false, allBlankCharsRegExp: '^[ ]+$',

ErrorMsg: function()
{
Expand All @@ -1056,7 +1088,7 @@ const loginPassword =
const excMaxLen = (this.maxLen + 1);
return (`${errStr} The string length must be less than ${excMaxLen} characters.`);
}
if (this.pswdStr.match (`${this.allBlankCharsRegExp}`) !== null)
if (this.pswdStr.match (this.allBlankCharsRegExp) !== null)
{ return (`${errStr} The string cannot be all blank spaces.`); }
if (this.pswdInvalid) { return loginPswdInvalidMsge; }
},
Expand All @@ -1073,7 +1105,7 @@ const loginPassword =
const excMaxLen = (this.maxLen + 1);
return (`${errStr}<br>The string length must be less than <b>${excMaxLen}</b> characters.</br>`);
}
if (this.pswdStr.match (`${this.allBlankCharsRegExp}`) !== null)
if (this.pswdStr.match (this.allBlankCharsRegExp) !== null)
{ return (`${errStr}<br>The string cannot be all blank spaces.<br>`); }
if (this.pswdInvalid) { return loginPswdInvalidHint; }
if (this.pswdVerified) { return loginPswdVerifiedMsg; }
Expand All @@ -1084,23 +1116,26 @@ const loginPassword =
const pswdStr = formField.value;
if (this.pswdStr !== pswdStr && eventID === 'onKEYUP')
{
this.pswdFocus = false;
this.pswdInvalid = false;
this.pswdVerified = false;
this.pswdUnverified = false;
}
this.pswdStr = pswdStr;
this.pswdLen = pswdStr.length;
if (this.pswdInvalid || this.pswdVerified || this.pswdUnverified ||
this.pswdLen < this.minLen || this.pswdLen > this.maxLen ||
this.pswdStr.match (`${this.allBlankCharsRegExp}`) !== null)

if (this.pswdLen < this.minLen || this.pswdLen > this.maxLen ||
this.pswdStr.match (this.allBlankCharsRegExp) !== null)
{ this.pswdFocus = true; return false; }
else if (this.pswdInvalid || this.pswdVerified || this.pswdUnverified)
{ return false; }
else
{ return true; }
}
};

/**----------------------------------------**/
/** Modified by Martinski W. [2025-Mar-07] **/
/** Modified by Martinski W. [2025-Jun-01] **/
/**----------------------------------------**/
function ValidatePasswordString (formField, eventID)
{
Expand All @@ -1110,21 +1145,30 @@ function ValidatePasswordString (formField, eventID)
$(formField).off('mouseover');
return true;
}

let retStatus;

if (eventID === 'onSAVE')
{ loginPassword.pswdFocus = true; }
else if (eventID === 'onKEYUP')
{ loginPassword.pswdFocus = false; }

if (loginPassword.pswdVerified || loginPassword.pswdUnverified)
{ retStatus = true; }
else
{
let retStatus;
if (loginPassword.pswdVerified || loginPassword.pswdUnverified)
{ retStatus = true; }
{ /** Set focus and red box ONLY when INVALID **/
retStatus = false;
if (loginPassword.pswdFocus)
{ formField.focus(); }
else
{
retStatus = false;
$(formField).addClass('Invalid');
}
formField.focus();
$(formField).on('mouseover',function(){return overlib(loginPassword.ErrorHint(),0,0);});
$(formField)[0].onmouseout = nd;
return retStatus;
{ formField.blur(); }
$(formField).addClass('Invalid');
}

/** Show tooltip message for ALL 3 statuses **/
$(formField).on('mouseover',function(){return overlib(loginPassword.ErrorHint(),0,0);});
$(formField)[0].onmouseout = nd;
return retStatus;
}

function togglePassword()
Expand Down Expand Up @@ -1432,9 +1476,9 @@ function ShowHintMsg (formField)
}
}

/**-------------------------------------**/
/** Added by Martinski W. [2025-Mar-07] **/
/**-------------------------------------**/
/**----------------------------------------**/
/** Modified by Martinski W. [2025-Jun-01] **/
/**----------------------------------------**/
function GetLoginPswdCheckStatus()
{
$.ajax({
Expand Down Expand Up @@ -1482,6 +1526,7 @@ function GetLoginPswdCheckStatus()
pswdStatusHint0 = loginPswdInvalidHint;
pswdStatusHint1 = loginPswdInvalidHint;
loginPassword.pswdInvalid = true;
loginPassword.pswdFocus = true;
break;
case 6: //Unknown//
pswdStatusText = 'Status:\n' + loginPswdCheckMsgStr;
Expand All @@ -1500,11 +1545,12 @@ function GetLoginPswdCheckStatus()
if (passwordFailed || pswdVerified || pswdUnverified)
{
if (passwordFailed)
{
{ /** Set focus and red box ONLY when INVALID **/
alert(`**ERROR**\n${loginPswdInvalidMsge}`);
$(pswdField).addClass('Invalid');
pswdField.focus();
$(pswdField).addClass('Invalid');
}
pswdField.focus();
/** Show tooltip message for ALL 3 statuses **/
$(pswdField).on('mouseover',function(){return overlib(pswdStatusHint0,0,0);});
$(pswdField)[0].onmouseout = nd;
}
Expand Down Expand Up @@ -1544,9 +1590,9 @@ function BlockChangelog()
document.form.submit();
}

/**----------------------------------------**/
/** Modified by Martinski W. [2025-Mar-07] **/
/**----------------------------------------**/
/**------------------------------------------**/
/** Modified by ExtremeFiretop [2025-May-18] **/
/**------------------------------------------**/
function InitializeFields()
{
console.log("Initializing fields...");
Expand Down Expand Up @@ -1642,7 +1688,10 @@ function InitializeFields()
{ tailscaleVPNEnabled.checked = (custom_settings.Allow_Updates_OverVPN === 'ENABLED'); }

if (script_AutoUpdate_Check)
{ script_AutoUpdate_Check.checked = (custom_settings.Allow_Script_Auto_Update === 'ENABLED'); }
{
script_AutoUpdate_Check.checked = (custom_settings.Allow_Script_Auto_Update === 'ENABLED');
UpdateForceScriptCheckboxState(script_AutoUpdate_Check?.checked);
}

if (betaToReleaseUpdatesEnabled)
{ betaToReleaseUpdatesEnabled.checked = (custom_settings.FW_Allow_Beta_Production_Up === 'ENABLED'); }
Expand Down Expand Up @@ -2292,29 +2341,55 @@ function Uninstall()
document.form.submit();
}

/**----------------------------------------**/
/** Modified by Martinski W. [2025-May-11] **/
/**----------------------------------------**/
/**---------------------------------------**/
/** Added by ExtremeFiretop [2025-May-18] **/
/**---------------------------------------**/
function UpdateForceScriptCheckboxState (autoUpdatesEnabled)
{
const forceCB = document.getElementById('ForceScriptUpdateCheck');
if (!forceCB) { return; }
forceCB.disabled = autoUpdatesEnabled;
forceCB.style.opacity = autoUpdatesEnabled ? '0.5' : '1';
// Clear "Force Script Update" if needed //
if (autoUpdatesEnabled) { forceCB.checked = false; }
}

/**------------------------------------------**/
/** Modified by ExtremeFiretop [2025-May-18] **/
/**------------------------------------------**/
function UpdateMerlinAUScript()
{
console.log("Initiating MerlinAU script update…");

let actionScriptValue;
let forceScriptUpdateCheck = document.getElementById('ForceScriptUpdateCheck');
const forceScriptUpdateCheck = document.getElementById('ForceScriptUpdateCheck');
const autoUpdatesEnabled = document.getElementById('Script_AutoUpdate_Check')?.checked;

let confirmText;
if (forceScriptUpdateCheck.checked)
{ /* user explicitly wants to install right now */
confirmText = "INSTALL UPDATE:\n" +
"Install the latest available MerlinAU script update now, " +
"even if the version is already current.\n\nContinue?";
}
else
{ /* normal check – message depends on auto‑update setting */
confirmText = "CHECK AND PROMPT:\n" +
"Check for a newer version of MerlinAU and prompt if found. " +
(autoUpdatesEnabled
? "It DOES install automatically!"
: "It does NOT install update automatically!") +
"\n\nContinue?";
}

let confirmOK = confirm(
forceScriptUpdateCheck.checked
? "INSTALL UPDATE:\nInstall the latest available MerlinAU script update now, even if version is current.\n\nContinue?"
: "CHECK AND PROMPT:\nCheck for a newer version of MerlinAU and prompt if found. It does NOT install update automatically!\n\nContinue?");
if (!confirmOK) { return; }
if (!confirm(confirmText)) { return; }

if (!forceScriptUpdateCheck.checked)
{ actionScriptValue = 'start_MerlinAUscrptupdate'; }
else
{ actionScriptValue = 'start_MerlinAUscrptupdate_force'; }
actionScriptValue = forceScriptUpdateCheck.checked
? 'start_MerlinAUscrptupdate_force'
: 'start_MerlinAUscrptupdate';

document.form.action_script.value = actionScriptValue;
document.form.action_wait.value = 10;
document.form.action_wait.value = 10;
showLoading();
document.form.submit();
}
Expand Down Expand Up @@ -2944,7 +3019,7 @@ function initializeCollapsibleSections()
</label>
</td>
<td>
<input type="checkbox" id="Script_AutoUpdate_Check" name="Script_AutoUpdate_Check"/>
<input type="checkbox" id="Script_AutoUpdate_Check" name="Script_AutoUpdate_Check" onchange="UpdateForceScriptCheckboxState(this.checked)"/>
<span id="Script_AutoUpdate_SchedText" name="Script_AutoUpdate_SchedText"
style="vertical-align:bottom; margin-left:15px; display:none; font-size: 12px; font-weight: bolder;"></span>
</td>
Expand Down
Loading