Skip to content

Commit 8a7a838

Browse files
More Code Improvements
- Added/modified the shell script to have the option to save/keep the current configuration file when uninstalling the add-on. This can be useful when a user needs to uninstalls all 3rd-party add-ons to do a full factory defaults reset, or simply wants to save the config file for re-install on a another (new?) router. - Added/modified the ASP file so the WebGUI page extracts the current version string from the shared custom settings instead of having a hard-coded string. - Some coding improvements.
1 parent 7d43d81 commit 8a7a838

File tree

2 files changed

+142
-86
lines changed

2 files changed

+142
-86
lines changed

MerlinAU.asp

Lines changed: 117 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929
<script language="JavaScript" type="text/javascript">
3030
3131
/**----------------------------**/
32-
/** Last Modified: 2025-Jan-17 **/
32+
/** Last Modified: 2025-Jan-18 **/
3333
/** Intended for 1.4.0 Release **/
3434
/**----------------------------**/
3535
3636
// Separate variables for server and AJAX settings //
3737
var advanced_settings = {};
3838
var custom_settings = {};
39-
var server_custom_settings = {};
39+
var shared_custom_settings = {};
4040
var ajax_custom_settings = {};
4141
let isFormSubmitting = false;
4242
@@ -353,10 +353,39 @@ function FWVersionStrToNum(verStr)
353353
return (verNum);
354354
}
355355
356+
/**----------------------------------------**/
357+
/** Modified by Martinski W. [2025-Jan-18] **/
358+
/**----------------------------------------**/
356359
function LoadCustomSettings()
357360
{
358-
server_custom_settings = <% get_custom_settings(); %>;
359-
console.log("Server Custom Settings Loaded:", server_custom_settings);
361+
shared_custom_settings = <% get_custom_settings(); %>;
362+
for (var prop in shared_custom_settings)
363+
{
364+
if (Object.prototype.hasOwnProperty.call(shared_custom_settings, prop))
365+
{
366+
// Remove any old entries that may have been left behind //
367+
if (prop.indexOf('MerlinAU') != -1 && prop.indexOf('MerlinAU_version_') == -1)
368+
{ eval('delete shared_custom_settings.' + prop); }
369+
}
370+
}
371+
console.log("Shared Custom Settings Loaded:", shared_custom_settings);
372+
}
373+
374+
/**-------------------------------------**/
375+
/** Added by Martinski W. [2025-Jan-18] **/
376+
/**-------------------------------------**/
377+
function GetScriptVersion (versionType)
378+
{
379+
var versionProp;
380+
if (versionType == 'local')
381+
{ versionProp = shared_custom_settings.MerlinAU_version_local; }
382+
else if (versionType == 'server')
383+
{ versionProp = shared_custom_settings.MerlinAU_version_server; }
384+
385+
if (typeof versionProp == 'undefined' || versionProp == null)
386+
{ return 'N/A'; }
387+
else
388+
{ return versionProp; }
360389
}
361390
362391
function prefixCustomSettings(settings, prefix)
@@ -661,79 +690,74 @@ function InitializeFields()
661690
}
662691
663692
/**----------------------------------------**/
664-
/** Modified by Martinski W. [2025-Jan-16] **/
693+
/** Modified by Martinski W. [2025-Jan-18] **/
665694
/**----------------------------------------**/
666-
function get_conf_file()
695+
function GetConfigSettings()
667696
{
668-
$.ajax({
669-
url: '/ext/MerlinAU/config.htm',
670-
dataType: 'text',
671-
error: function(xhr)
672-
{
673-
console.error("Failed to fetch config.htm:", xhr.statusText);
674-
setTimeout(get_conf_file, 1000); // Retry after 1 second
675-
},
676-
success: function(data)
697+
$.ajax({
698+
url: '/ext/MerlinAU/config.htm',
699+
dataType: 'text',
700+
error: function(xhr)
701+
{
702+
console.error("Failed to fetch config.htm:", xhr.statusText);
703+
setTimeout(GetConfigSettings, 1000);
704+
},
705+
success: function(data)
706+
{
707+
// Tokenize the data while respecting quoted values
708+
var tokenList = tokenize(data);
709+
710+
for (var i = 0; i < tokenList.length; i++)
677711
{
678-
// Tokenize the data while respecting quoted values
679-
var tokens = tokenize(data);
712+
var token = tokenList[i];
713+
714+
if (token.includes('='))
715+
{
716+
// Handle "key=value" format //
717+
var splitIndex = token.indexOf('=');
718+
var key = token.substring(0, splitIndex).trim();
719+
var value = token.substring(splitIndex + 1).trim();
680720
681-
// Iterate through tokens to extract key-value pairs
682-
for (var i = 0; i < tokens.length; i++)
721+
// Remove surrounding quotes if present
722+
if (value.startsWith('"') && value.endsWith('"'))
723+
{ value = value.substring(1, value.length - 1); }
724+
725+
assignAjaxSetting(key, value);
726+
}
727+
else
683728
{
684-
var token = tokens[i];
729+
// Handle "key value" format //
730+
var key = token.trim();
731+
var value = '';
685732
686-
if (token.includes('='))
733+
// Ensure there's a next token for the value //
734+
if (i + 1 < tokenList.length)
687735
{
688-
// Handle key=value format
689-
var splitIndex = token.indexOf('=');
690-
var key = token.substring(0, splitIndex).trim();
691-
var value = token.substring(splitIndex + 1).trim();
736+
value = tokenList[i + 1].trim();
692737
693-
// Remove surrounding quotes if present
694-
if (value.startsWith('"') && value.endsWith('"')) {
695-
value = value.substring(1, value.length - 1);
696-
}
738+
// Remove surrounding quotes if present //
739+
if (value.startsWith('"') && value.endsWith('"'))
740+
{ value = value.substring(1, value.length - 1); }
697741
698742
assignAjaxSetting(key, value);
743+
i++; // Skip the next token as it's already processed
699744
}
700745
else
701-
{
702-
// Handle key value format
703-
var key = token.trim();
704-
var value = '';
705-
706-
// Ensure there's a next token for the value
707-
if (i + 1 < tokens.length)
708-
{
709-
value = tokens[i + 1].trim();
710-
711-
// Remove surrounding quotes if present
712-
if (value.startsWith('"') && value.endsWith('"')) {
713-
value = value.substring(1, value.length - 1);
714-
}
715-
716-
assignAjaxSetting(key, value);
717-
i++; // Skip the next token as it's already processed
718-
}
719-
else
720-
{
721-
console.warn(`No value found for key: ${key}`);
722-
}
723-
}
746+
{ console.warn(`No value found for key: ${key}`); }
724747
}
748+
}
725749
726-
console.log("AJAX Custom Settings Loaded:", ajax_custom_settings);
750+
console.log("AJAX Custom Settings Loaded:", ajax_custom_settings);
727751
728-
// Merge both server and AJAX settings
729-
custom_settings = Object.assign({}, server_custom_settings, ajax_custom_settings);
730-
console.log("Merged Custom Settings:", custom_settings);
752+
// Merge both server and AJAX settings //
753+
custom_settings = Object.assign({}, shared_custom_settings, ajax_custom_settings);
754+
console.log("Merged Custom Settings:", custom_settings);
731755
732-
// Initialize fields with the merged settings
733-
InitializeFields();
734-
GetExternalCheckResults();
735-
}
736-
});
756+
// Initialize fields with the merged settings //
757+
InitializeFields();
758+
GetExternalCheckResults();
759+
}
760+
});
737761
}
738762
739763
// Helper function to tokenize the input string, respecting quoted substrings //
@@ -743,10 +767,10 @@ function tokenize(input)
743767
return input.match(regex) || [];
744768
}
745769
746-
// Helper function to assign settings based on key
770+
// Helper function to assign settings based on key //
747771
function assignAjaxSetting(key, value)
748772
{
749-
// Normalize key to uppercase for case-insensitive comparison
773+
// Normalize key to uppercase for case-insensitive comparison //
750774
var keyUpper = key.toUpperCase();
751775
752776
switch (true) {
@@ -829,10 +853,10 @@ function assignAjaxSetting(key, value)
829853
ajax_custom_settings.FW_New_Update_Notifications_Date = value;
830854
break;
831855
832-
// Additional AJAX settings can be handled here
856+
// Additional AJAX settings can be handled here //
833857
834858
default:
835-
// Optionally handle or log unknown settings
859+
// Optionally handle or log unknown settings //
836860
break;
837861
}
838862
}
@@ -875,23 +899,35 @@ function SetCurrentPage()
875899
876900
function convertToStatus(value)
877901
{
878-
if (typeof value === 'boolean') return value ? 'ENABLED' : 'DISABLED';
879-
if (typeof value === 'string') {
880-
return (value.toLowerCase() === 'true' || value.toLowerCase() === 'enabled') ? 'ENABLED' : 'DISABLED';
881-
}
882-
return 'DISABLED';
902+
if (typeof value === 'boolean') return value ? 'ENABLED' : 'DISABLED';
903+
if (typeof value === 'string')
904+
{ return (value.toLowerCase() === 'true' || value.toLowerCase() === 'enabled') ? 'ENABLED' : 'DISABLED'; }
905+
return 'DISABLED';
906+
}
907+
908+
/**-------------------------------------**/
909+
/** Added by Martinski W. [2025-Jan-18] **/
910+
/**-------------------------------------**/
911+
function UpdateScriptVersion()
912+
{
913+
var localVers = GetScriptVersion('local');
914+
var serverVers = GetScriptVersion('server');
915+
916+
$('#headerTitle').text ('MerlinAU Dashboard v' + localVers);
917+
$('#footerTitle').text ('MerlinAU v' + localVers + ' by ExtremeFiretop & Martinski W.');
883918
}
884919
885920
/**----------------------------------------**/
886-
/** Modified by Martinski W. [2025-Jan-17] **/
921+
/** Modified by Martinski W. [2025-Jan-18] **/
887922
/**----------------------------------------**/
888923
function initial()
889924
{
890925
isFormSubmitting = false;
891926
SetCurrentPage();
892927
LoadCustomSettings();
893-
get_conf_file();
928+
GetConfigSettings();
894929
show_menu();
930+
UpdateScriptVersion();
895931
896932
// Debugging iframe behavior //
897933
var hiddenFrame = document.getElementById('hidden_frame');
@@ -966,12 +1002,12 @@ function SaveActionsConfig()
9661002
"MerlinAU_FW_New_Update_TUFWBuildType"
9671003
];
9681004
ADVANCED_KEYS.forEach(function (key){
969-
if (server_custom_settings.hasOwnProperty(key))
970-
{ delete server_custom_settings[key]; }
1005+
if (shared_custom_settings.hasOwnProperty(key))
1006+
{ delete shared_custom_settings[key]; }
9711007
});
9721008
9731009
// Merge Server Custom Settings and prefixed Action form settings //
974-
var updatedSettings = Object.assign({}, server_custom_settings, prefixedActionSettings);
1010+
var updatedSettings = Object.assign({}, shared_custom_settings, prefixedActionSettings);
9751011
9761012
// Save merged settings to the hidden input field //
9771013
document.getElementById('amng_custom').value = JSON.stringify(updatedSettings);
@@ -1052,20 +1088,20 @@ function SaveAdvancedConfig()
10521088
// Prefix only Advanced settings
10531089
var prefixedAdvancedSettings = prefixCustomSettings(advanced_settings, 'MerlinAU_');
10541090
1055-
// Remove any action keys from server_custom_settings to avoid overwriting //
1091+
// Remove any action keys from shared_custom_settings to avoid overwriting //
10561092
var ACTION_KEYS = [
10571093
"MerlinAU_credentials_base64",
10581094
"MerlinAU_FW_New_Update_Postponement_Days",
10591095
"MerlinAU_CheckChangeLog",
10601096
"MerlinAU_FW_Update_Check"
10611097
];
10621098
ACTION_KEYS.forEach(function (key){
1063-
if (server_custom_settings.hasOwnProperty(key))
1064-
{ delete server_custom_settings[key]; }
1099+
if (shared_custom_settings.hasOwnProperty(key))
1100+
{ delete shared_custom_settings[key]; }
10651101
});
10661102
10671103
// Merge Server Custom Settings and prefixed Advanced settings
1068-
var updatedSettings = Object.assign({}, server_custom_settings, prefixedAdvancedSettings);
1104+
var updatedSettings = Object.assign({}, shared_custom_settings, prefixedAdvancedSettings);
10691105
10701106
// Save merged settings to the hidden input field
10711107
document.getElementById('amng_custom').value = JSON.stringify(updatedSettings);
@@ -1284,7 +1320,7 @@ function initializeCollapsibleSections()
12841320
<tr style="background-color:#4D595D;">
12851321
<td valign="top">
12861322
<div>&nbsp;</div>
1287-
<div class="formfonttitle" style="text-align:center;">MerlinAU Dashboard v1.4.0</div>
1323+
<div class="formfonttitle" id="headerTitle" style="text-align:center;">MerlinAU</div>
12881324
<div style="margin:10px 0 10px 5px;" class="splitLine"></div>
12891325
<div class="formfontdesc">This is the MerlinAU add-on integrated into the router WebUI.</div>
12901326
<div style="line-height:10px;">&nbsp;</div>
@@ -1569,7 +1605,7 @@ function initializeCollapsibleSections()
15691605
value="Save" class="button_gen savebutton" name="button">
15701606
</div>
15711607
</form></td></tr></tbody></table>
1572-
<div style="margin-top:10px;text-align:center;">MerlinAU v1.4.0 by ExtremeFiretop &amp; Martinski W.</div>
1608+
<div id="footerTitle" style="margin-top:10px;text-align:center;">MerlinAU</div>
15731609
</td></tr></tbody></table></td></tr></table></td>
15741610
<td width="10"></td>
15751611
</tr></table></form>

MerlinAU.sh

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# Original Creation Date: 2023-Oct-01 by @ExtremeFiretop.
66
# Official Co-Author: @Martinski W. - Date: 2023-Nov-01
7-
# Last Modified: 2025-Jan-16
7+
# Last Modified: 2025-Jan-18
88
###################################################################
99
set -u
1010

@@ -8744,16 +8744,26 @@ _DoInstallation_()
87448744
_MainMenu_
87458745
}
87468746

8747-
##------------------------------------------##
8748-
## Modified by ExtremeFiretop [2024-Dec-21] ##
8749-
##------------------------------------------##
8747+
##----------------------------------------##
8748+
## Modified by Martinski W. [2025-Jan-18] ##
8749+
##----------------------------------------##
87508750
_DoUnInstallation_()
87518751
{
8752-
printf "\nAre you sure you want to uninstall $ScriptFileName script now"
8752+
printf "\n${BOLDct}Are you sure you want to uninstall $ScriptFileName script now${NOct}"
87538753
! _WaitForYESorNO_ && return 0
87548754

87558755
if ! _AcquireLock_ cliFileLock ; then return 1 ; fi
87568756

8757+
local doSaveConfig=false
8758+
local savedCFGPath="${SCRIPTS_PATH}/${SCRIPT_NAME}_CFG.SAVED.TXT"
8759+
8760+
printf "\n${BOLDct}Do you want to keep/save the $SCRIPT_NAME configuration file${NOct}"
8761+
if _WaitForYESorNO_
8762+
then
8763+
doSaveConfig=true
8764+
mv -f "$CONFIG_FILE" "$savedCFGPath"
8765+
fi
8766+
87578767
_DelFWAutoUpdateHook_
87588768
_DelFWAutoUpdateCronJob_
87598769
_DelScriptAutoUpdateHook_
@@ -8770,6 +8780,7 @@ _DoUnInstallation_()
87708780
fi
87718781

87728782
if rm -fr "${SETTINGS_DIR:?}" && \
8783+
rm -fr "${SCRIPT_WEB_DIR:?}" && \
87738784
rm -fr "${FW_BIN_BASE_DIR:?}/$ScriptDirNameD" && \
87748785
rm -fr "${FW_LOG_BASE_DIR:?}/$ScriptDirNameD" && \
87758786
rm -fr "${FW_ZIP_BASE_DIR:?}/$ScriptDirNameD" && \
@@ -8779,6 +8790,15 @@ _DoUnInstallation_()
87798790
else
87808791
Say "${CRITct}**ERROR**: Uninstallation failed.${NOct}"
87818792
fi
8793+
8794+
if "$doSaveConfig"
8795+
then
8796+
if mkdir -p "$SETTINGS_DIR"
8797+
then
8798+
chmod 755 "$SETTINGS_DIR"
8799+
mv -f "$savedCFGPath" "$CONFIG_FILE"
8800+
fi
8801+
fi
87828802
_DoExit_ 0
87838803
}
87848804

0 commit comments

Comments
 (0)