Skip to content
Snippets Groups Projects
Commit ca3ee677 authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Merge branch 'dd_upload_processor_arc_viewer_config_load_refactor' into 'master'

DD arc viewer & upload processor: Refactor of how the configuration files are read. Arc viewer: Control characters are no longer needed for color settings.

See merge request !305
parents 105d5c49 da4e727b
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 ...@@ -15,21 +15,21 @@ maxTextFileSize=5M
[COLORS] [COLORS]
; The "Archive:" text ; The "Archive:" text
archiveFilenameHdrText=nwh archiveFilenameHdrText=nwh
; Archive filename ; Archive filename
archiveFilename=ngh archiveFilename=ngh
; The column header line above the file list ; The column header line above the file list
headerLine=nyh headerLine=nyh
; The line between the header line and the file list ; The line between the header line and the file list
headerSeparatorLine=nkh headerSeparatorLine=nkh
; File numbers ; File numbers
fileNums=nmh fileNums=nmh
; File information columns ; File information columns
fileSize=nw fileSize=nw
fileDate=ng fileDate=ng
fileTime=nr fileTime=nr
filename=nc filename=nc
; For subdirectories ; For subdirectories
subdir=ngh subdir=ngh
; For lightbar mode, highlighted filenames will have this color: ; For lightbar mode, highlighted filenames will have this color:
highlightedFile=n4wh4 highlightedFile=nwh4
\ No newline at end of file \ No newline at end of file
...@@ -83,6 +83,9 @@ ...@@ -83,6 +83,9 @@
* 2022-05-17 Eric Oulashin When extracting an archive with Synchronet's * 2022-05-17 Eric Oulashin When extracting an archive with Synchronet's
* internal archiver, extracts with path information * internal archiver, extracts with path information
* to trust that filename characters are safe. * 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"; "use strict";
...@@ -115,8 +118,8 @@ load(gStartupPath + "dd_arc_viewer_cleanup.js"); ...@@ -115,8 +118,8 @@ load(gStartupPath + "dd_arc_viewer_cleanup.js");
// Version information // Version information
var gDDArcViewerVersion = "1.04"; var gDDArcViewerVersion = "1.05";
var gDDArcViewerVerDate = "2022-05-14"; var gDDArcViewerVerDate = "2023-08-08";
var gDDArcViewerProgName = "Digital Distortion Archive Viewer"; var gDDArcViewerProgName = "Digital Distortion Archive Viewer";
...@@ -232,7 +235,6 @@ if (!configFileRead) ...@@ -232,7 +235,6 @@ if (!configFileRead)
} }
// Now, the fun begins..
// gRootWorkDir will containing the name of the root work directory. This // gRootWorkDir will containing the name of the root work directory. This
// is where we'll extract the archive. // is where we'll extract the archive.
...@@ -328,85 +330,37 @@ function ReadConfig(pCfgFilePath) ...@@ -328,85 +330,37 @@ function ReadConfig(pCfgFilePath)
{ {
if (fileTypeCfgFile.length > 0) if (fileTypeCfgFile.length > 0)
{ {
var allFileTypeCfg = fileTypeCfgFile.iniGetAllObjects();
fileTypeSettingsRead = true; fileTypeSettingsRead = true;
// Read each line from the config file and set the for (var i = 0; i < allFileTypeCfg.length; ++i)
// 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)
{
// 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 startIndex = fileLine.indexOf("[") + 1; var filenameExt = allFileTypeCfg[i].name; // Filename extension
var endIndex = fileLine.lastIndexOf("]"); var viewableFile = new ViewableFile();
var ext = fileLine.substr(startIndex, endIndex-startIndex).toUpperCase(); viewableFile.extension = filenameExt;
// If the filename extension is different than the last one for (var prop in allFileTypeCfg[i])
// 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)
{ {
if ((viewableFile != null) && (viewableFile != undefined) && (filenameExt.length > 0)) 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")
{ {
gViewableFileTypes[filenameExt] = viewableFile; if (typeof(allFileTypeCfg[i][prop]) === "string")
} {
filenameExt = ext; var valueUpper = allFileTypeCfg[i][prop].toUpperCase();
viewableFile = new ViewableFile(); viewableFile.isText = (valueUpper == "YES" || valueUpper == "TRUE");
viewableFile.extension = ext;
} }
continue; else if (typeof(allFileTypeCfg[i][prop]) === "boolean")
viewableFile.isText = allFileTypeCfg[i][prop];
} }
// 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(); fileTypeCfgFile.close();
} }
// Read the extractable and viewable file configuration from the Synchronet // 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 // configuration and add any that we haven't seen in dd_arc_viewer_file_types.cfg
var SCFGFileCmds = getFileExtractAndViewCmdsFromSCFG(); var SCFGFileCmds = getFileExtractAndViewCmdsFromSCFG();
...@@ -436,94 +390,56 @@ function ReadConfig(pCfgFilePath) ...@@ -436,94 +390,56 @@ function ReadConfig(pCfgFilePath)
{ {
if (genCfgFile.length > 0) if (genCfgFile.length > 0)
{ {
var behaviorSettings = genCfgFile.iniGetObject("BEHAVIOR");
var colorSettings = genCfgFile.iniGetObject("COLORS");
genSettingsRead = true; 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]")
{
settingsMode = "behavior";
continue;
}
else if (fileLine.toUpperCase() == "[COLORS]")
{
settingsMode = "colors";
continue;
}
// 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 // General/behavior settings
// into the setting name (before the =) and the value (after the for (var prop in behaviorSettings)
// equals sign).
equalsPos = fileLine.indexOf("=");
if (equalsPos > 0)
{ {
// Read the setting & value, and trim leading & trailing spaces. var propUpper = prop.toUpperCase();
setting = trimSpaces(fileLine.substr(0, equalsPos), true, false, true); if (propUpper == "INTERFACESTYLE")
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")
{ {
var valueUpper = behaviorSettings[prop].toUpperCase();
// Ensure that the first character is uppercase and the // Ensure that the first character is uppercase and the
// rest is lower-case. // rest is lower-case.
if ((value == "LIGHTBAR") || (value == "TRADITIONAL")) if ((valueUpper == "LIGHTBAR") || (valueUpper == "TRADITIONAL"))
{ {
gGenConfig.interfaceStyle = value.substr(0, 1).toUpperCase() gGenConfig.interfaceStyle = behaviorSettings[prop].substr(0, 1).toUpperCase()
+ value.substr(1).toLowerCase(); + behaviorSettings[prop].substr(1).toLowerCase();
} }
} }
else if (settingUpper == "INPUTTIMEOUTMS") else if (propUpper == "INPUTTIMEOUTMS")
gGenConfig.inputTimeoutMS = +value; {
else if (settingUpper == "MAXARCFILESIZE") var timeoutMSInt = parseInt(behaviorSettings[prop]);
gGenConfig.maxArcFileSize = sizeStrToBytes(value); if (!isNaN(timeoutMSInt) && timeoutMSInt > 0)
else if (settingUpper == "MAXTEXTFILESIZE") gGenConfig.inputTimeoutMS = timeoutMSInt;
gGenConfig.maxTextFileSize = sizeStrToBytes(value);
}
else if (settingsMode == "colors")
gGenConfig.colors[setting] = value;
} }
else if (propUpper == "MAXARCFILESIZE")
gGenConfig.maxArcFileSize = sizeStrToBytes(behaviorSettings[prop]);
else if (propUpper == "MAXTEXTFILESIZE")
gGenConfig.maxTextFileSize = sizeStrToBytes(behaviorSettings[prop]);
} }
genCfgFile.close(); // Color settings
var onlySyncAttrsRegexWholeWord = new RegExp("^[\x01krgybmcw01234567hinq,;\.dtlasz]+$", 'i');
for (var prop in gGenConfig.colors)
{
if (colorSettings.hasOwnProperty(prop))
{
// 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();
}
return (fileTypeSettingsRead && genSettingsRead); return (fileTypeSettingsRead && genSettingsRead);
} }
...@@ -2338,3 +2254,27 @@ function charStr(pChar, pNumTimes) ...@@ -2338,3 +2254,27 @@ function charStr(pChar, pNumTimes)
str += pChar; str += pChar;
return str; 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 Digital Distortion Archive Viewer
Version 1.04 Version 1.05
Release date: 2022-05-16 Release date: 2023-08-08
by by
...@@ -280,8 +280,11 @@ folows: ...@@ -280,8 +280,11 @@ folows:
setting=value setting=value
where "setting" is the behavior setting or color, and "value" is the corresponding where "setting" is the behavior setting or color, and "value" is the
value for the setting/color. The colors are Synchronet color codes. 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 Also, comments are allowed in the configuration file. Comments begin with a
semicolon (;). semicolon (;).
......
...@@ -2,6 +2,9 @@ Revision History for Digital Distortion Archive Viewer ...@@ -2,6 +2,9 @@ Revision History for Digital Distortion Archive Viewer
====================================================== ======================================================
Version Date Description 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. 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 Now has built-in support for the same archive types that
Synchronet has built-in (zip, 7z, tgz, etc.). Other Synchronet has built-in (zip, 7z, tgz, etc.). Other
......
...@@ -9,16 +9,23 @@ ...@@ -9,16 +9,23 @@
* BBS: Digital Distortion * BBS: Digital Distortion
* BBS address: digdist.bbsindex.com * BBS address: digdist.bbsindex.com
* *
* Date Author Version Description * Date Author Description
* 2009-12-25- * 2009-12-25-
* 2009-12-28 Eric Oulashin Initial development * 2009-12-28 Eric Oulashin Initial development
* 2009-12-29 Eric Oulashin 1.00 Initial public release * 2009-12-29 Eric Oulashin Version 1.00
* 2022-06-08 Eric Oulashin 1.01 Made fixes to get the scanner functionality working properly in Linux * Initial public release
* 2022-06-11 Eric Oulashin 1.02 Improved file/dir permissions more: Set file permissions after extracting * 2022-06-08 Eric Oulashin Version 1.01
Made fixes to get the scanner functionality working properly in Linux
* 2022-06-11 Eric Oulashin Version 1.02
* Improved file/dir permissions more: Set file permissions after extracting
* an archive so that they're all readable. * an archive so that they're all readable.
* 2022-06-11 Eric Oulashin 1.03 Removed the chmod stuff, as it is actually not needed. * 2022-06-11 Eric Oulashin Version 1.03
* 2023-08-06 Eric Oulashin 1.04 Now uses Synchronet's built-in archiver (added in Synchronet 3.19), * Removed the chmod stuff, as it is actually not needed.
* 2023-08-06 Eric Oulashin Version 1.04
* Now uses Synchronet's built-in archiver (added in Synchronet 3.19),
* if available, to extract archives. * if available, to extract archives.
* 2023-08-07 Eric Oulashin Version 1.05
* Internal refactor of how the configuration files are read
*/ */
/* Command-line arguments: /* Command-line arguments:
...@@ -46,8 +53,8 @@ gStartupPath = backslash(gStartupPath.replace(/[\/\\][^\/\\]*$/,'')); ...@@ -46,8 +53,8 @@ gStartupPath = backslash(gStartupPath.replace(/[\/\\][^\/\\]*$/,''));
load(gStartupPath + "ddup_cleanup.js"); load(gStartupPath + "ddup_cleanup.js");
// Version information // Version information
var gDDUPVersion = "1.04"; var gDDUPVersion = "1.05";
var gDDUPVerDate = "2023-08-06"; var gDDUPVerDate = "2023-08-07";
// Store whether or not this is running in Windows // Store whether or not this is running in Windows
var gRunningInWindows = /^WIN/.test(system.platform.toUpperCase()); var gRunningInWindows = /^WIN/.test(system.platform.toUpperCase());
...@@ -157,7 +164,7 @@ function main() ...@@ -157,7 +164,7 @@ function main()
// Originally I had this script output the version date, but now I'm not sure // Originally I had this script output the version date, but now I'm not sure
// if I want to do that.. // if I want to do that..
//console.print(" \1w\1h(\1b" + gDDUPVerDate + "\1w)"); //console.print(" \1w\1h(\1b" + gDDUPVerDate + "\1w)");
console.print("\1n"); console.attributes = "N";
console.crlf(); console.crlf();
// Process the file // Process the file
...@@ -205,11 +212,11 @@ function ScannableFile(pExtension, pExtractCmd, pScanOption) ...@@ -205,11 +212,11 @@ function ScannableFile(pExtension, pExtractCmd, pScanOption)
this.scanOption = "scan"; // The scan option ("scan", "always pass", "always fail") this.scanOption = "scan"; // The scan option ("scan", "always pass", "always fail")
// If the parameters are valid, then use them to set the object properties. // If the parameters are valid, then use them to set the object properties.
if ((pExtension != null) && (pExtension != undefined) && (typeof(pExtension) == "string")) if ((pExtension != null) && (typeof(pExtension) == "string"))
this.extension = pExtension; this.extension = pExtension;
if ((pExtractCmd != null) && (pExtractCmd != undefined) && (typeof(pExtractCmd) == "string")) if ((pExtractCmd != null) && (typeof(pExtractCmd) == "string"))
this.extractCmd = pExtractCmd; this.extractCmd = pExtractCmd;
if ((pScanOption != null) && (pScanOption != undefined) && (typeof(pScanOption) == "string")) if ((pScanOption != null) && (typeof(pScanOption) == "string"))
this.scanOption = pScanOption; this.scanOption = pScanOption;
} }
...@@ -243,7 +250,7 @@ function processFile(pFilename) ...@@ -243,7 +250,7 @@ function processFile(pFilename)
// Display the program header stuff - The name of the file being scanned // Display the program header stuff - The name of the file being scanned
// and the status header line // and the status header line
var justFilename = getFilenameFromPath(pFilename); var justFilename = getFilenameFromPath(pFilename);
console.print("\1n\1w\1hScanning \1b" + justFilename.substr(0, 70)); console.print("\1n\1w\1hScanning \1b" + justFilename);
console.print("\1n\r\n\1b\1" + "7 File Scan Status \1n\r\n"); console.print("\1n\r\n\1b\1" + "7 File Scan Status \1n\r\n");
// If the skipScanIfSysop option is enabled and the user is a sysop, // If the skipScanIfSysop option is enabled and the user is a sysop,
...@@ -305,6 +312,7 @@ function processFile(pFilename) ...@@ -305,6 +312,7 @@ function processFile(pFilename)
{ {
// Extract the file to the work directory // Extract the file to the work directory
printf(gStatusPrintfStr, "\1m\1h", "Extracting the file..."); printf(gStatusPrintfStr, "\1m\1h", "Extracting the file...");
console.crlf();
var errorStr = extractFileToDir(pFilename, workDir); var errorStr = extractFileToDir(pFilename, workDir);
if (errorStr.length == 0) if (errorStr.length == 0)
{ {
...@@ -399,26 +407,25 @@ function processFile(pFilename) ...@@ -399,26 +407,25 @@ function processFile(pFilename)
// file scan. // file scan.
function scanFilesInDir(pDir) function scanFilesInDir(pDir)
{ {
var retObj = {
cmdOutput: [],
returnCode: 0
};
// If pDir is unspecified, then just return. // If pDir is unspecified, then just return.
if (typeof(pDir) != "string") if (typeof(pDir) != "string")
{ {
var retObj = new Object();
retObj.cmdOutput = new Array();
retObj.returnCode = -1; retObj.returnCode = -1;
return retObj; return retObj;
} }
if (pDir.length == 0) if (pDir.length == 0)
{ {
var retObj = new Object();
retObj.cmdOutput = new Array();
retObj.returnCode = -2; retObj.returnCode = -2;
return retObj; return retObj;
} }
// Also, just return if gGenCfg.scanCmd is blank. // Also, just return if gGenCfg.scanCmd is blank.
if (gGenCfg.scanCmd.length == 0) if (gGenCfg.scanCmd.length == 0)
{ {
var retObj = new Object();
retObj.cmdOutput = new Array();
retObj.returnCode = -3; retObj.returnCode = -3;
return retObj; return retObj;
} }
...@@ -427,8 +434,6 @@ function scanFilesInDir(pDir) ...@@ -427,8 +434,6 @@ function scanFilesInDir(pDir)
if ((/\/$/.test(pDir)) || (/\\$/.test(pDir))) if ((/\/$/.test(pDir)) || (/\\$/.test(pDir)))
pDir = pDir.substr(0, pDir.length-1); pDir = pDir.substr(0, pDir.length-1);
var retObj = null; // Will be used to capture the return from the scan commands
// If the virus scan command contains %FILESPEC%, then // If the virus scan command contains %FILESPEC%, then
// replace %FILESPEC% with pDir and run the scan command. // replace %FILESPEC% with pDir and run the scan command.
if (gGenCfg.scanCmd.indexOf("%FILESPEC%") > -1) if (gGenCfg.scanCmd.indexOf("%FILESPEC%") > -1)
...@@ -466,9 +471,10 @@ function scanFilesInDir(pDir) ...@@ -466,9 +471,10 @@ function scanFilesInDir(pDir)
{ {
// There are no files. So create retObj with default settings // There are no files. So create retObj with default settings
// for a good result. // for a good result.
retObj = new Object(); retObj = {
retObj.returnCode = 0; returnCode: 0,
retObj.cmdOutput = new Array(); cmdOutput = []
};
} }
*/ */
} }
...@@ -476,9 +482,7 @@ function scanFilesInDir(pDir) ...@@ -476,9 +482,7 @@ function scanFilesInDir(pDir)
{ {
// gGenCfg.scanCmd doesn't contain %FILESPEC%, so set up // gGenCfg.scanCmd doesn't contain %FILESPEC%, so set up
// retObj with a non-zero return code (for failure) // retObj with a non-zero return code (for failure)
retObj = new Object();
retObj.returnCode = -4; retObj.returnCode = -4;
retObj.cmdOutput = new Array();
retObj.cmdOutput.push("The virus scanner is not set up correctly."); retObj.cmdOutput.push("The virus scanner is not set up correctly.");
} }
...@@ -501,145 +505,59 @@ function ReadConfigFile(pCfgFilePath) ...@@ -501,145 +505,59 @@ function ReadConfigFile(pCfgFilePath)
{ {
if (fileTypeCfgFile.length > 0) if (fileTypeCfgFile.length > 0)
{ {
var allFileTypeCfg = fileTypeCfgFile.iniGetAllObjects();
fileTypeSettingsRead = true; fileTypeSettingsRead = true;
// Read each line from the config file and set the for (var i = 0; i < allFileTypeCfg.length; ++i)
// 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 scannableFile = null; // Will be used to create & store scannable file options
while (!fileTypeCfgFile.eof)
{
// 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 startIndex = fileLine.indexOf("[") + 1; var filenameExt = allFileTypeCfg[i].name; // Filename extension
var endIndex = fileLine.lastIndexOf("]"); var scannableFile = new ScannableFile(filenameExt, "", "scan");
var ext = fileLine.substr(startIndex, endIndex-startIndex).toUpperCase(); for (var prop in allFileTypeCfg[i])
// If the filename extension is different than the last one
// we've seen, then:
// 1. If scannableFile is not null, then add it to gScannableFileTypes.
// 2. Create a new one (referenced as scannableFile).
if (ext != filenameExt)
{
if ((scannableFile != null) && (scannableFile != undefined) &&
(filenameExt.length > 0))
{
gFileTypeCfg[filenameExt] = scannableFile;
}
filenameExt = ext;
scannableFile = new ScannableFile(ext, "", "scan");
}
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. var propUpper = prop.toUpperCase();
option = trimSpaces(fileLine.substr(0, pos), true, false, true).toUpperCase(); if (propUpper === "EXTRACT")
optionValue = trimSpaces(fileLine.substr(pos+1), true, false, true); scannableFile.extractCmd = allFileTypeCfg[i][prop];
else if (propUpper === "SCANOPTION")
if (option == "EXTRACT") scannableFile.scanOption = allFileTypeCfg[i][prop];
scannableFile.extractCmd = optionValue;
else if (option == "SCANOPTION")
scannableFile.scanOption = optionValue;
} }
gFileTypeCfg[filenameExt] = scannableFile;
} }
} }
fileTypeCfgFile.close(); fileTypeCfgFile.close();
} }
// Read the general program configuration // Read the general configuration
var genSettingsRead = false; var genSettingsRead = false;
var genCfgFile = new File(pCfgFilePath + "ddup.cfg"); var genCfgFile = new File(pCfgFilePath + "ddup.cfg");
if (genCfgFile.open("r")) if (genCfgFile.open("r"))
{ {
if (genCfgFile.length > 0) if (genCfgFile.length > 0)
{ {
var settingsObj = genCfgFile.iniGetObject();
genSettingsRead = true; genSettingsRead = true;
var fileLine = null; // A line read from the file for (var prop in settingsObj)
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 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)
{
// 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);
// Skip this one if the value is blank.
if (value.length == 0)
continue;
// Set the appropriate value in the settings object. // Set the appropriate value in the settings object.
var settingUpper = prop.toUpperCase();
if (settingUpper == "SCANCMD") if (settingUpper == "SCANCMD")
gGenCfg.scanCmd = value; gGenCfg.scanCmd = settingsObj[prop];
else if (settingUpper == "SKIPSCANIFSYSOP") else if (settingUpper == "SKIPSCANIFSYSOP")
gGenCfg.skipScanIfSysop = (value.toUpperCase() == "YES"); {
if (typeof(settingsObj[prop]) === "string")
gGenCfg.skipScanIfSysop = (settingsObj[prop].toUpperCase() == "YES");
else if (typeof(settingsObj[prop]) === "boolean")
gGenCfg.skipScanIfSysop = settingsObj[prop];
}
else if (settingUpper == "PAUSEATEND") else if (settingUpper == "PAUSEATEND")
gGenCfg.pauseAtEnd = (value.toUpperCase() == "YES"); {
if (typeof(settingsObj[prop]) === "string")
{
var valueUpper = settingsObj[prop].toUpperCase();
gGenCfg.pauseAtEnd = (valueUpper == "YES" || valueUpper == "TRUE");
}
else if (typeof(settingsObj[prop]) === "boolean")
gGenCfg.pauseAtEnd = settingsObj[prop];
} }
} }
genCfgFile.close();
} }
} }
...@@ -872,7 +790,6 @@ function extractFileToDir(pFilename, pWorkDir) ...@@ -872,7 +790,6 @@ function extractFileToDir(pFilename, pWorkDir)
// due to certain characters in the filename. // due to certain characters in the filename.
var numFilesExtracted = arcFile.extract(pWorkDir, true); var numFilesExtracted = arcFile.extract(pWorkDir, true);
builtInExtractSucceeded = true; builtInExtractSucceeded = true;
if (user.is_sysop) console.print("\x01n\r\n\x01gExtracted with Synchronet's built-in Archive support\x01n\r\n\r\n"); // Temporary
} }
catch (e) catch (e)
{ {
......
Digital Distortion Upload Processor Digital Distortion Upload Processor
Version 1.04 Version 1.05
Release date: 2023-08-06 Release date: 2023-08-07
by by
......
...@@ -2,6 +2,8 @@ Revision History for Digital Distortion Upload Processor ...@@ -2,6 +2,8 @@ Revision History for Digital Distortion Upload Processor
======================================================== ========================================================
Version Date Description 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 1.04 2023-08-06 Now uses Synchronet's built-in archiver (added in
Synchronet 3.19), if available, to extract archives. Synchronet 3.19), if available, to extract archives.
1.03 2022-06-11 Removed the chmod updates because they're actually not 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.
Please register or to comment