Skip to content
Snippets Groups Projects
Commit da4e727b authored by Eric Oulashin's avatar Eric Oulashin Committed by Rob Swindell
Browse files

DD arc viewer & upload processor: Refactor of how the configuration files are...

DD arc viewer & upload processor: Refactor of how the configuration files are read. Arc viewer: Control characters are no longer needed for color settings.
parent 105d5c49
No related branches found
No related tags found
2 merge requests!463MRC mods by Codefenix (2024-10-20),!305DD arc viewer & upload processor: Refactor of how the configuration files are read. Arc viewer: Control characters are no longer needed for color settings.
......@@ -15,21 +15,21 @@ maxTextFileSize=5M
[COLORS]
; The "Archive:" text
archiveFilenameHdrText=nwh
archiveFilenameHdrText=nwh
; Archive filename
archiveFilename=ngh
archiveFilename=ngh
; The column header line above the file list
headerLine=nyh
headerLine=nyh
; The line between the header line and the file list
headerSeparatorLine=nkh
headerSeparatorLine=nkh
; File numbers
fileNums=nmh
fileNums=nmh
; File information columns
fileSize=nw
fileDate=ng
fileTime=nr
filename=nc
fileSize=nw
fileDate=ng
fileTime=nr
filename=nc
; For subdirectories
subdir=ngh
subdir=ngh
; For lightbar mode, highlighted filenames will have this color:
highlightedFile=n4wh4
\ No newline at end of file
highlightedFile=nwh4
\ No newline at end of file
......@@ -83,6 +83,9 @@
* 2022-05-17 Eric Oulashin When extracting an archive with Synchronet's
* internal archiver, extracts with path information
* to trust that filename characters are safe.
* 2023-08-08 Eric Oulashin Version 1.05
* Refactored how the configuration files are loaded.
* Colors in dd_arc_viewer.cfg no longer need the control character.
*/
"use strict";
......@@ -115,8 +118,8 @@ load(gStartupPath + "dd_arc_viewer_cleanup.js");
// Version information
var gDDArcViewerVersion = "1.04";
var gDDArcViewerVerDate = "2022-05-14";
var gDDArcViewerVersion = "1.05";
var gDDArcViewerVerDate = "2023-08-08";
var gDDArcViewerProgName = "Digital Distortion Archive Viewer";
......@@ -232,7 +235,6 @@ if (!configFileRead)
}
// Now, the fun begins..
// gRootWorkDir will containing the name of the root work directory. This
// is where we'll extract the archive.
......@@ -328,85 +330,37 @@ function ReadConfig(pCfgFilePath)
{
if (fileTypeCfgFile.length > 0)
{
var allFileTypeCfg = fileTypeCfgFile.iniGetAllObjects();
fileTypeSettingsRead = true;
// Read each line from the config file and set the
// various options.
var pos = 0; // Index of = in the file lines
var fileLine = "";
var filenameExt = ""; // Archive filename extension
var option = ""; // Configuration option
var optionValue = ""; // Configuration option value
var optionValueUpper; // Upper-cased configuration option value
var viewableFile = null; // Will be used to create & store viewable archive options
while (!fileTypeCfgFile.eof)
for (var i = 0; i < allFileTypeCfg.length; ++i)
{
// Read the line from the config file, look for a =, and
// if found, read the option & value and set them
// in cfgObj.
fileLine = fileTypeCfgFile.readln(1024);
// fileLine should be a string, but I've seen some cases
// where it isn't, so check its type.
if (typeof(fileLine) != "string")
continue;
// If the line is blank or starts with with a semicolon
// (the comment character), then skip it.
if ((fileLine.length == 0) || (fileLine.substr(0, 1) == ";"))
continue;
// Look for a file extension in square brackets ([ and ]).
// If found, then set filenameExt and continue onto the next line.
// Note: This regular expression allows whitespace around the [...].
if (/^\s*\[.*\]\s*$/.test(fileLine))
var filenameExt = allFileTypeCfg[i].name; // Filename extension
var viewableFile = new ViewableFile();
viewableFile.extension = filenameExt;
for (var prop in allFileTypeCfg[i])
{
var startIndex = fileLine.indexOf("[") + 1;
var endIndex = fileLine.lastIndexOf("]");
var ext = fileLine.substr(startIndex, endIndex-startIndex).toUpperCase();
// If the filename extension is different than the last one
// we've seen, then:
// 1. If viewableFile is not null, then add it to gViewableFileTypes.
// 2. Create a new one (referenced as viewableFile).
if (ext != filenameExt)
var propUpper = prop.toUpperCase();
if (propUpper == "VIEW")
viewableFile.viewCmd = allFileTypeCfg[i][prop];
else if (propUpper == "EXTRACT")
viewableFile.extractCmd = allFileTypeCfg[i][prop];
else if (propUpper == "ISTEXT")
{
if ((viewableFile != null) && (viewableFile != undefined) && (filenameExt.length > 0))
if (typeof(allFileTypeCfg[i][prop]) === "string")
{
gViewableFileTypes[filenameExt] = viewableFile;
var valueUpper = allFileTypeCfg[i][prop].toUpperCase();
viewableFile.isText = (valueUpper == "YES" || valueUpper == "TRUE");
}
filenameExt = ext;
viewableFile = new ViewableFile();
viewableFile.extension = ext;
else if (typeof(allFileTypeCfg[i][prop]) === "boolean")
viewableFile.isText = allFileTypeCfg[i][prop];
}
continue;
}
// If filenameExt is blank, then continue onto the next line.
if (filenameExt.length == 0)
continue;
// If we're here, then filenameExt is set, and this is a valid
// line to process.
// Look for an = in the line, and if found, split into
// option & value.
pos = fileLine.indexOf("=");
if (pos > -1)
{
// Extract the option & value, trimming leading & trailing spaces.
option = trimSpaces(fileLine.substr(0, pos), true, false, true).toUpperCase();
optionValue = trimSpaces(fileLine.substr(pos+1), true, false, true);
if (option == "VIEW")
viewableFile.viewCmd = optionValue;
else if (option == "EXTRACT")
viewableFile.extractCmd = optionValue;
else if (option == "ISTEXT")
viewableFile.isText = (optionValue.toUpperCase() == "YES");
}
gViewableFileTypes[filenameExt] = viewableFile;
}
}
fileTypeCfgFile.close();
}
// Read the extractable and viewable file configuration from the Synchronet
// configuration and add any that we haven't seen in dd_arc_viewer_file_types.cfg
var SCFGFileCmds = getFileExtractAndViewCmdsFromSCFG();
......@@ -436,93 +390,55 @@ function ReadConfig(pCfgFilePath)
{
if (genCfgFile.length > 0)
{
var behaviorSettings = genCfgFile.iniGetObject("BEHAVIOR");
var colorSettings = genCfgFile.iniGetObject("COLORS");
genSettingsRead = true;
var settingsMode = "";
var fileLine = null; // A line read from the file
var equalsPos = 0; // Position of a = in the line
var commentPos = 0; // Position of the start of a comment
var setting = null; // A setting name (string)
var settingUpper = null; // Upper-case setting name
var value = null; // A value for a setting (string)
while (!genCfgFile.eof)
{
// Read the next line from the config file.
fileLine = genCfgFile.readln(1024);
// fileLine should be a string, but I've seen some cases
// where it isn't, so check its type.
if (typeof(fileLine) != "string")
continue;
// If the line starts with with a semicolon (the comment
// character) or is blank, then skip it.
if ((fileLine.substr(0, 1) == ";") || (fileLine.length == 0))
continue;
// If in the "behavior" section, then set the behavior-related variables.
if (fileLine.toUpperCase() == "[BEHAVIOR]")
// General/behavior settings
for (var prop in behaviorSettings)
{
var propUpper = prop.toUpperCase();
if (propUpper == "INTERFACESTYLE")
{
settingsMode = "behavior";
continue;
var valueUpper = behaviorSettings[prop].toUpperCase();
// Ensure that the first character is uppercase and the
// rest is lower-case.
if ((valueUpper == "LIGHTBAR") || (valueUpper == "TRADITIONAL"))
{
gGenConfig.interfaceStyle = behaviorSettings[prop].substr(0, 1).toUpperCase()
+ behaviorSettings[prop].substr(1).toLowerCase();
}
}
else if (fileLine.toUpperCase() == "[COLORS]")
else if (propUpper == "INPUTTIMEOUTMS")
{
settingsMode = "colors";
continue;
var timeoutMSInt = parseInt(behaviorSettings[prop]);
if (!isNaN(timeoutMSInt) && timeoutMSInt > 0)
gGenConfig.inputTimeoutMS = timeoutMSInt;
}
else if (propUpper == "MAXARCFILESIZE")
gGenConfig.maxArcFileSize = sizeStrToBytes(behaviorSettings[prop]);
else if (propUpper == "MAXTEXTFILESIZE")
gGenConfig.maxTextFileSize = sizeStrToBytes(behaviorSettings[prop]);
}
// If settingsMode is blank, then skip this line.
if (settingsMode.length == 0)
continue;
// If the line has a semicolon anywhere in it, then remove
// everything from the semicolon onward.
commentPos = fileLine.indexOf(";");
if (commentPos > -1)
fileLine = fileLine.substr(0, commentPos);
// Look for an equals sign, and if found, separate the line
// into the setting name (before the =) and the value (after the
// equals sign).
equalsPos = fileLine.indexOf("=");
if (equalsPos > 0)
// Color settings
var onlySyncAttrsRegexWholeWord = new RegExp("^[\x01krgybmcw01234567hinq,;\.dtlasz]+$", 'i');
for (var prop in gGenConfig.colors)
{
if (colorSettings.hasOwnProperty(prop))
{
// Read the setting & value, and trim leading & trailing spaces.
setting = trimSpaces(fileLine.substr(0, equalsPos), true, false, true);
settingUpper = setting.toUpperCase();
value = trimSpaces(fileLine.substr(equalsPos+1), true, false, true).toUpperCase();
if (settingsMode == "behavior")
{
// Skip this one if the value is blank.
if (value.length == 0)
continue;
// Set the appropriate value in the settings object.
if (settingUpper == "INTERFACESTYLE")
{
// Ensure that the first character is uppercase and the
// rest is lower-case.
if ((value == "LIGHTBAR") || (value == "TRADITIONAL"))
{
gGenConfig.interfaceStyle = value.substr(0, 1).toUpperCase()
+ value.substr(1).toLowerCase();
}
}
else if (settingUpper == "INPUTTIMEOUTMS")
gGenConfig.inputTimeoutMS = +value;
else if (settingUpper == "MAXARCFILESIZE")
gGenConfig.maxArcFileSize = sizeStrToBytes(value);
else if (settingUpper == "MAXTEXTFILESIZE")
gGenConfig.maxTextFileSize = sizeStrToBytes(value);
}
else if (settingsMode == "colors")
gGenConfig.colors[setting] = value;
// Make sure the value is a string (for attrCodeStr() etc; in some cases, such as a background attribute of 4, it will be a number)
var value = colorSettings[prop].toString();
// If the value doesn't have any control characters, then add the control character
// before attribute characters
if (!/\x01/.test(value))
value = attrCodeStr(value);
if (onlySyncAttrsRegexWholeWord.test(value))
gGenConfig.colors[prop] = value;
}
}
genCfgFile.close();
}
genCfgFile.close();
}
return (fileTypeSettingsRead && genSettingsRead);
......@@ -1207,9 +1123,9 @@ function writeFileListHeader(pFilename)
if (writeFileListHeader.topHelp3 == undefined)
{
writeFileListHeader.topHelp3 = gGenConfig.colors.headerSeparatorLine
+ charStr(HORIZONTAL_SINGLE, 4) + " " + charStr(HORIZONTAL_SINGLE, 8) + " "
+ charStr(HORIZONTAL_SINGLE, 10) + " " + charStr(HORIZONTAL_SINGLE, 5) + " "
+ charStr(HORIZONTAL_SINGLE, console.screen_columns - 32);
+ charStr(HORIZONTAL_SINGLE, 4) + " " + charStr(HORIZONTAL_SINGLE, 8) + " "
+ charStr(HORIZONTAL_SINGLE, 10) + " " + charStr(HORIZONTAL_SINGLE, 5) + " "
+ charStr(HORIZONTAL_SINGLE, console.screen_columns - 32);
// Add line characters to the end of the screen.
//for (var x = 30; x < console.screen_columns - 2; ++x)
// writeFileListHeader.topHelp3 += HORIZONTAL_SINGLE;
......@@ -2337,4 +2253,28 @@ function charStr(pChar, pNumTimes)
for (var i = 0; i < pNumTimes; ++i)
str += pChar;
return str;
}
// Given a string of attribute characters, this function inserts the control code
// in front of each attribute character and returns the new string.
//
// Parameters:
// pAttrCodeCharStr: A string of attribute characters (i.e., "YH" for yellow high)
//
// Return value: A string with the control character inserted in front of the attribute characters
function attrCodeStr(pAttrCodeCharStr)
{
if (typeof(pAttrCodeCharStr) !== "string")
return "";
var str = "";
// See this page for Synchronet color attribute codes:
// http://wiki.synchro.net/custom:ctrl-a_codes
for (var i = 0; i < pAttrCodeCharStr.length; ++i)
{
var currentChar = pAttrCodeCharStr.charAt(i);
if (/[krgybmcwKRGYBMCWHhIiEeFfNn01234567]/.test(currentChar))
str += "\x01" + currentChar;
}
return str;
}
\ No newline at end of file
Digital Distortion Archive Viewer
Version 1.04
Release date: 2022-05-16
Version 1.05
Release date: 2023-08-08
by
......@@ -280,8 +280,11 @@ folows:
setting=value
where "setting" is the behavior setting or color, and "value" is the corresponding
value for the setting/color. The colors are Synchronet color codes.
where "setting" is the behavior setting or color, and "value" is the
corresponding value for the setting/color. The colors are Synchronet color
codes. The control character is not needed for the color codes; for sample, to
set a color of high-intensity green, you could use "gh" (or "ngh" if you want
to ensure that the normal attribute gets set first).
Also, comments are allowed in the configuration file. Comments begin with a
semicolon (;).
......
......@@ -2,6 +2,9 @@ Revision History for Digital Distortion Archive Viewer
======================================================
Version Date Description
------- ---- -----------
1.05 2023-08-08 Internal refactor of how the configuration files are
loaded. Colors in dd_arc_viewer.cfg no longer need the
control character.
1.04 2022-05-16 Updated to use the new Archive class in Synchronet 3.19.
Now has built-in support for the same archive types that
Synchronet has built-in (zip, 7z, tgz, etc.). Other
......
This diff is collapsed.
Digital Distortion Upload Processor
Version 1.04
Release date: 2023-08-06
Version 1.05
Release date: 2023-08-07
by
......
......@@ -2,6 +2,8 @@ Revision History for Digital Distortion Upload Processor
========================================================
Version Date Description
------- ---- -----------
1.05 2023-08-07 Internal refactor of how the configuration files are
read. Behavior is the same.
1.04 2023-08-06 Now uses Synchronet's built-in archiver (added in
Synchronet 3.19), if available, to extract archives.
1.03 2022-06-11 Removed the chmod updates because they're actually not
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment