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

Merge branch 'dd_archive_viewer_archive_class_update' into 'master'

DD Archive Viewer now supports the built-in Archive class in Synchronet 3.19

See merge request !299
parents c2c3cdfc 93c87efc
No related branches found
No related tags found
2 merge requests!463MRC mods by Codefenix (2024-10-20),!299DD Archive Viewer now supports the built-in Archive class in Synchronet 3.19
Pipeline #4566 passed
......@@ -50,7 +50,7 @@
* functions.
* 2009-12-15 Eric Oulashin Version Pre1.02
* Updated to store the name of the file to view
* in a variable called fileToView. Also added
* in a variable called gFileToView. Also added
* some code to read the name of the file to view
* from DDArcViewerFilename.txt in the node
* directory if the filename is not specified on
......@@ -68,26 +68,34 @@
* This relies on the arguments being passed with
* double-quotes around them, as in other
* programming languages.
* 2009-12-25 Eric Oulashin Verison 1.04 Beta
* Removed the extra declaration for fileToView from
* the else case (the script should use the global one).
* Renamed fileToView to gFileToView.
* 2022-04-12 Eric Oulashin Started updating to use the new Archive class in
* Synchronet 3.19.
* 2022-05-14 Eric Oulashin Version 1.04
* Made a couple fixes and improvements.
* Updated to read the file viewable and extractable
* commands from the Synchronet configuration and use
* any of those that aren't in dd_arc_viewer_file_types.cfg.
* dd_arc_viewer_file_types.cfg takes precedence.
* 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.
*/
"use strict";
/* Command-line arguments:
1 (argv[0]): The name of the file to view
*/
if (typeof(require) === "function")
require("sbbsdefs.js", "K_UPPER");
else
load("sbbsdefs.js");
// Temporary (for testing) - Printing out command-line arguments
//console.print("argv[0]:" + argv[0] + ":\r\n\1p");
//console.print("argv: " + argv + "\r\n\1p");
// End Temporary
// Unit tests
/*
test_fixPathSlashes();
test_getFilenameExtension();
exit(0);
*/
// End Unit tests
// Determine the script's execution directory.
// This code is a trick that was created by Deuce, suggested by Rob
......@@ -95,17 +103,20 @@ exit(0);
// in. I've shortened the code a little.
// Note: gStartupPath will include the trailing slash.
var gStartupPath = '.';
try { throw dig.dist(dist); } catch(e) { gStartupPath = e.fileName; }
gStartupPath = backslash(gStartupPath.replace(/[\/\\][^\/\\]*$/,''));
var gThisScriptFilename = "";
try { throw dig.dist(dist); } catch(e) {
gStartupPath = backslash(e.fileName.replace(/[\/\\][^\/\\]*$/,''));
gThisScriptFilename = file_getname(e.fileName);
}
// We need the deltree() and withoutTrailingSlash() functions
// from the cleanup script.
load(gStartupPath + "DDArcViewerCleanup.js");
load(gStartupPath + "dd_arc_viewer_cleanup.js");
// Version information
var gDDArcViewerVersion = "1.03";
var gDDArcViewerVerDate = "2009-12-20";
var gDDArcViewerVersion = "1.04";
var gDDArcViewerVerDate = "2022-05-14";
var gDDArcViewerProgName = "Digital Distortion Archive Viewer";
......@@ -115,14 +126,14 @@ var KEY_ENTER = CTRL_M;
var ESC_KEY = "\x1b";
// Characters for display
var UP_ARROW_DISPLAY = "";
var DOWN_ARROW_DISPLAY = "";
var UPPER_LEFT_SINGLE = "Ú";
var HORIZONTAL_SINGLE = "Ä";
var UPPER_RIGHT_SINGLE = "¿";
var VERTICAL_SINGLE = "³";
var LOWER_LEFT_SINGLE = "À";
var LOWER_RIGHT_SINGLE = "Ù";
var UP_ARROW_DISPLAY = ascii(24);
var DOWN_ARROW_DISPLAY = ascii(25);
var UPPER_LEFT_SINGLE = "\xDA";
var HORIZONTAL_SINGLE = "\xC4";
var UPPER_RIGHT_SINGLE = "\xBF";
var VERTICAL_SINGLE = "\xB3";
var LOWER_LEFT_SINGLE = "\xC0";
var LOWER_RIGHT_SINGLE = "\xD9";
// Determine which slash character to use for paths, depending
......@@ -136,33 +147,35 @@ var gPathSlash = (/^WIN/.test(system.platform.toUpperCase())) ? "\\" : "/";
//
// properties/indexes will be the filename extensions
// (strings), and the values will be the OS command to view the file.
var gViewableFileTypes = new Object();
var gViewableFileTypes = {
};
// General configuration
var gGenConfig = new Object();
// Set the general configuration defaults
gGenConfig.interfaceStyle = "Lightbar";
gGenConfig.inputTimeoutMS = 300000;
gGenConfig.maxArcFileSize = 1073741824; // 1.0GB
gGenConfig.maxTextFileSize = 5242880; // 5.0MB
gGenConfig.colors = new Object();
gGenConfig.colors.archiveFilenameHdrText = "nwh";
gGenConfig.colors.archiveFilename = "ngh";
gGenConfig.colors.headerLine = "nyh";
gGenConfig.colors.headerSeparatorLine = "nkh";
gGenConfig.colors.fileNums = "nmh";
gGenConfig.colors.fileSize = "nw";
gGenConfig.colors.fileDate = "ng";
gGenConfig.colors.fileTime = "nr";
gGenConfig.colors.filename = "nc";
gGenConfig.colors.subdir = "ngh";
gGenConfig.colors.highlightedFile = "n4wh";
var gGenConfig = {
interfaceStyle: "Lightbar",
inputTimeoutMS: 300000,
maxArcFileSize: 1073741824, // 1.0GB
maxTextFileSize: 5242880, // 5.0MB
colors: {
archiveFilenameHdrText: "\x01n\x01w\x01h",
archiveFilename: "\x01n\x01g\x01h",
headerLine: "\x01n\x01y\x01h",
headerSeparatorLine: "\x01n\x01k\x01h",
fileNums: "\x01n\x01m\x01h",
fileSize: "\x01n\x01w",
fileDate: "\x01n\x01g",
fileTime: "\x01n\x01r",
filename: "\x01n\x01c",
subdir: "\x01n\x01g\x01h",
highlightedFile: "\x01n\x01" + "4\x01w\x01h"
}
};
// If the filename was specified on the command line, then use that
// for the filename. Otherwise, read the name of the file to view
// from DDArcViewerFilename.txt in the node directory.
var fileToView = "";
var gFileToView = "";
if (argv.length > 0)
{
if (typeof(argv[0]) == "string")
......@@ -170,17 +183,17 @@ if (argv.length > 0)
// Make sure the arguments are correct (in case they have spaces),
// then use the first one.
var fixedArgs = fixArgs(argv);
if ((typeof(fixedArgs[0]) == "string") && (fixedArgs[0].length > 0))
fileToView = fixedArgs[0];
if ((typeof(fixedArgs[0]) === "string") && (fixedArgs[0].length > 0))
gFileToView = fixedArgs[0];
else
{
console.print("nchError: ncBlank filename argument given.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cBlank filename argument given.\r\n\x01p");
exit(-2);
}
}
else
{
console.print("nchError: ncUnknown command-line argument specified.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cUnknown command-line argument specified.\r\n\x01p");
exit(-1);
}
}
......@@ -190,23 +203,21 @@ else
// This is a workaround for file/directory names with spaces in
// them, which would get separated into separate command-line
// arguments for JavaScript scripts.
var fileToView = "";
var filenameFileFilename = system.node_dir + "DDArcViewerFilename.txt";
var filenameFile = new File(filenameFileFilename);
if (filenameFile.open("r"))
{
if (!filenameFile.eof)
fileToView = filenameFile.readln(2048);
gFileToView = filenameFile.readln(2048);
filenameFile.close();
}
}
// A filename must be specified as the first argument, so give an error and return
// if not.
//if ((argv[0] == undefined) || (argv[0] == null) || (typeof(argv[0]) != "string"))
if (fileToView.length == 0)
if (gFileToView.length == 0)
{
console.print("nchError: ncNo filename specified to view.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cNo filename specified to view.\r\n\x01p");
exit(1);
}
......@@ -215,8 +226,8 @@ var configFileRead = ReadConfig(gStartupPath);
// If the configuration file wasn't read, then output an error and exit.
if (!configFileRead)
{
console.print("nchError: ncThis viewer was unable to read its configuration\r\n");
console.print("file.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cThis viewer was unable to read its configuration\r\n");
console.print("file.\r\n\x01p");
exit(2);
}
......@@ -232,7 +243,7 @@ var gRootWorkDirExists = mkdir(gRootWorkDir);
// If the work dir was not created, then output an error and exit.
if (!gRootWorkDirExists)
{
console.print("nchError: ncCould not create the temporary work directory.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cCould not create the temporary work directory.\r\n\x01p");
exit(6);
}
......@@ -243,14 +254,14 @@ const gANSISupported = console.term_supports(USER_ANSI);
var useLightbar = (gANSISupported && (gGenConfig.interfaceStyle == "Lightbar"));
// Write a note in the log that the user is viewing the archive.
var gTopLevelFilename = fixPathSlashes(fileToView);
var gTopLevelFilename = fixPathSlashes(gFileToView);
bbs.log_str(user.alias + " is viewing a file: " + gTopLevelFilename);
// View the file
var gListFilesFunction = useLightbar ? listFiles_Lightbar : listFiles_Traditional;
var retObj = viewFile(gTopLevelFilename, gRootWorkDir, gListFilesFunction);
// Clean up (remove the root work directory, etc.)
console.print("ncViewer cleanupi...n\r\n");
console.print("\x01n\x01cViewer cleanup\x01i...\x01n\r\n");
console.line_counter = 0; // To prevent pausing
deltree(gRootWorkDir);
......@@ -287,11 +298,11 @@ function ViewableFile(pExtension, pViewCmd, pExtractCmd)
// If pExtension, pViewCmd, or pExtractCmd are valid, then use them to set
// the object parameters.
if ((pExtension != null) && (pExtension != undefined) && (typeof(pExtension) == "string"))
if ((pExtension != null) && (typeof(pExtension) === "string"))
this.extension = pExtension;
if ((pViewCmd != null) && (pViewCmd != undefined) && (typeof(pViewCmd) == "string"))
if ((pViewCmd != null) && (typeof(pViewCmd) === "string"))
this.viewCmd = pViewCmd;
if ((pExtractCmd != null) && (pExtractCmd != undefined) && (typeof(pExtractCmd) == "string"))
if ((pExtractCmd != null) && (typeof(pExtractCmd) === "string"))
this.extractCmd = pExtractCmd;
}
......@@ -312,7 +323,7 @@ function ReadConfig(pCfgFilePath)
{
// Read the file type settings
var fileTypeSettingsRead = false;
var fileTypeCfgFile = new File(pCfgFilePath + "DDArcViewerFileTypes.cfg");
var fileTypeCfgFile = new File(pCfgFilePath + "dd_arc_viewer_file_types.cfg");
if (fileTypeCfgFile.open("r"))
{
if (fileTypeCfgFile.length > 0)
......@@ -358,8 +369,7 @@ function ReadConfig(pCfgFilePath)
// 2. Create a new one (referenced as viewableFile).
if (ext != filenameExt)
{
if ((viewableFile != null) && (viewableFile != undefined) &&
(filenameExt.length > 0))
if ((viewableFile != null) && (viewableFile != undefined) && (filenameExt.length > 0))
{
gViewableFileTypes[filenameExt] = viewableFile;
}
......@@ -397,10 +407,31 @@ function ReadConfig(pCfgFilePath)
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();
for (var SCFGFilenameExt in SCFGFileCmds)
{
if (!gViewableFileTypes.hasOwnProperty(SCFGFilenameExt))
{
var viewableFile = new ViewableFile();
viewableFile.extension = SCFGFilenameExt;
if (SCFGFileCmds[SCFGFilenameExt].hasOwnProperty("extractCmd"))
viewableFile.extractCmd = SCFGFileCmds[SCFGFilenameExt].extractCmd;
if (SCFGFileCmds[SCFGFilenameExt].hasOwnProperty("viewCmd"))
{
// Only use the view command if it doesn't run this script
var viewCmdUpper = SCFGFileCmds[SCFGFilenameExt].viewCmd.toUpperCase();
if (viewCmdUpper.indexOf(gThisScriptFilename.toUpperCase()) < 0)
viewableFile.viewCmd = SCFGFileCmds[SCFGFilenameExt].viewCmd;
}
gViewableFileTypes[filenameExt] = viewableFile;
}
}
// Read the general program configuration
var genSettingsRead = false;
var genCfgFile = new File(pCfgFilePath + "DDArcViewer.cfg");
var genCfgFile = new File(pCfgFilePath + "dd_arc_viewer.cfg");
if (genCfgFile.open("r"))
{
if (genCfgFile.length > 0)
......@@ -528,35 +559,167 @@ function sizeStrToBytes(pSizeStr)
numBytes = Math.floor(numBytes);
return numBytes;
}
// Returns an object of filename extensions and their extract and commands
// (if any) as configured in SCFG > File Options > Extractable Files.
//
// Return value: An object where the properties are filename extensions and
// the values are objects containing the following properties,
// if configured (either of these might not exist):
// extractCmd: The configured extract command for the file type
// viewCmd: The configured view command for the file type
function getFileExtractAndViewCmdsFromSCFG()
{
var fileCmds = {};
// See exportcfg.js for an example of using cnflib.js
var cnflib = load({}, "cnflib.js");
var file_cnf = cnflib.read("file.cnf");
if (typeof(file_cnf) === "object")
{
// File extract commands
for (var i = 0; i < file_cnf.fextr.length; ++i)
{
// If the current user has access to the command, then add it.
if (bbs.compare_ars(file_cnf.fextr[i].ars))
{
var filenameExt = file_cnf.fextr[i].extension.toUpperCase();
if (!fileCmds.hasOwnProperty(filenameExt)) fileCmds[filenameExt] = {};
fileCmds[filenameExt].extractCmd = file_cnf.fextr[i].cmd;
}
}
// File view commands
for (var i = 0; i < file_cnf.fview.length; ++i)
{
// If the current user has access to the command, then add it.
if (bbs.compare_ars(file_cnf.fview[i].ars))
{
var filenameExt = file_cnf.fview[i].extension.toUpperCase();
if (!fileCmds.hasOwnProperty(filenameExt)) fileCmds[filenameExt] = {};
fileCmds[filenameExt].viewCmd = file_cnf.fview[i].cmd;
}
}
}
return fileCmds;
}
// Extracts an archive to a directory. Returns an array containing the
// output of the extraction command.
// Extracts an archive to a directory.
//
// Parameters:
// pArchiveFilename: The name of the archive file to extract
// pExtractCmd: The command to extract the file (from the configuration)
// pDestDir: The directory to which to extract the file
//
// Return value: An array containing the output of the extraction command.
function extractArchive(pArchiveFilename, pExtractCmd, pDestDir)
// Return value: An object containing the following properties:
// success: Boolean - Whether or not extraction was successful
// usedArchiveClass: Boolean - Whether or not the Archive class was used
// (added in Synchronet 3.19)
// error: String - Will contain any applicable error message on failure
// output: An array containing the output of the extraction command, if
// an external extract command was run. If the Archive class
// is available, this will likely be empty.
function extractArchive(pArchiveFilename, pDestDir)
{
var retObj = {
success: false,
usedArchiveClass: false,
error: "",
output: ""
};
// Make sure all the slashes in the filename and the destination directory
// are correct for the platform.
var arcFilename = fixPathSlashes(pArchiveFilename);
var destDir = fixPathSlashes(pDestDir);
// If the Archive class is available (added in Synchronet 3.19), then
// use it to extract the archive. Otherwise, use the configured external
// archiver command to extract it.
if (typeof(Archive) === "function")
{
retObj.usedArchiveClass = true;
var arcFile = new Archive(arcFilename);
try
{
// Extract with path information (trust the archive that any
// filename characters are okay). If we don't extract with
// path information, then Synchronet may reject some filenames
// due to certain characters in the filename.
if (arcFile.extract(destDir, true) > 0)
retObj.success = true;
else
retObj.error = "No files extracted";
}
catch (e)
{
// Synchronet's internal archiver was unable to extract it. Try
// with an external archiver, if a command is configured.
log(LOG_ERR, "DDArcViewer: Synchronet internal archiver failed to extract " + arcFilename + ": " + e);
var externRet = extractArchiveWithExernalArc(pArchiveFilename, pDestDir);
retObj.output = externRet.output;
retObj.success = externRet.success;
}
}
else
{
var externRet = extractArchiveWithExernalArc(pArchiveFilename, pDestDir);
retObj.output = externRet.output;
retObj.success = externRet.success;
}
return retObj;
}
// Extracts an archive to a directory using an external archiver.
//
// Parameters:
// pArchiveFilename: The name of the archive file to extract
// pDestDir: The directory to which to extract the file
//
// Return value: An object containing the following properties:
// success: Boolean - Whether or not extraction was successful
// output: An array containing the output of the extraction command, if
// an external extract command was run. If the Archive class
// is available, this will likely be empty.
function extractArchiveWithExernalArc(pArchiveFilename, pDestDir)
{
var retObj = {
success: false,
output: ""
};
// Make sure all the slashes in the filename and the destination directory
// are correct for the platform.
var filename = fixPathSlashes(pArchiveFilename);
var arcFilename = fixPathSlashes(pArchiveFilename);
// Make sure there is an external archiver command for this file type
var filenameExt = getFilenameExtension(arcFilename).toUpperCase();
if (!gViewableFileTypes.hasOwnProperty(filenameExt) || gViewableFileTypes[filenameExt].extractCmd.length == 0)
{
retObj.success = false;
console.attributes = "N";
console.crlf();
console.print("\x01h\x01gThere is no extractor configured for \x01c" + filenameExt + "\x01n");
console.crlf();
console.pause();
return retObj;
}
var destDir = fixPathSlashes(pDestDir);
// Build the extract command, and then execute it.
// Note: This puts double-quotes around the filename and destination dir
// to deal with spaces.
var command = pExtractCmd.replace("%FILENAME%", "\"" + filename + "\"");
var extractCmd = gViewableFileTypes[filenameExt].extractCmd;
var command = extractCmd.replace("%FILENAME%", "\"" + arcFilename + "\"");
// I was originally going to replace %FILESPEC% with * (to extract all files), but
// that doesn't work on *nix because * expands to all files in the current dir.
// And if the filespec isn't specified, it extracts all files anyway.
//command = command.replace("%FILESPEC%", "*"); // Extract all files
command = command.replace("%FILESPEC%", ""); // Extract all files
command = command.replace("%TO_DIR%", "\"" + withoutTrailingSlash(destDir) + "\"");
return (execCmdWithOutput(command));
retObj.output = execCmdWithOutput(command);
retObj.success = true;
return retObj;
}
// Views a file.
......@@ -572,21 +735,22 @@ function extractArchive(pArchiveFilename, pExtractCmd, pDestDir)
// errorCode: An code representing an error. 0 = no error.
function viewFile(pFilename, pWorkDir, pListFilesFunction)
{
var retObj = new Object();
retObj.errorCode = 0;
var retObj = {
errorCode: 0
};
// Determine the filename's extension
var filenameExt = getFilenameExtension(pFilename);
var filenameExt = getFilenameExtension(pFilename).toUpperCase();
if (filenameExt.length == 0)
{
console.print("nchError: ncThe filename has no extension.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cThe filename has no extension.\r\n\x01p");
retObj.errorCode = 3;
return(retObj);
}
// If the filename extension is unknown, then output an error and exit.
if ((gViewableFileTypes[filenameExt] == undefined) || (gViewableFileTypes[filenameExt] == null))
{
console.print("nchError: ncThe filename extension (" + filenameExt + ") is unknown.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cThe filename extension (" + filenameExt + ") is unknown.\r\n\x01p");
retObj.errorCode = 4;
return(retObj);
}
......@@ -602,8 +766,7 @@ function viewFile(pFilename, pWorkDir, pListFilesFunction)
// to view it.
if ((gGenConfig.maxTextFileSize > 0) && (file_size(pFilename) > gGenConfig.maxTextFileSize))
{
//console.print("Here 1\r\n"); // Temporary
console.print("nchError: ncThe file is too big to view.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cThe file is too big to view.\r\n\x01p");
retObj.errorCode = 8;
return(retObj);
}
......@@ -616,19 +779,18 @@ function viewFile(pFilename, pWorkDir, pListFilesFunction)
// to view it.
if ((gGenConfig.maxArcFileSize > 0) && (file_size(pFilename) > gGenConfig.maxArcFileSize))
{
//console.print("Here 2\r\n"); // Temporary
//console.print("File size: " + file_size(pFilename) + ", limit: " + gGenConfig.maxarcFileSize + "\r\n"); // Temporary
console.print("nchError: ncThe file is too big to view.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cThe file is too big to view.\r\n\x01p");
retObj.errorCode = 8;
return(retObj);
}
// If there is no extract command specified for the archive type, then
// output an error and exit.
if (gViewableFileTypes[filenameExt].extractCmd.length == 0)
// If the Archive class isn't available (added in Synchronet 3.19) and there
// is no extract command specified for the archive type, then output an error
// and exit.
if (typeof(Archive) !== "function" && (!gViewableFileTypes.hasOwnProperty(filenameExt) || gViewableFileTypes[filenameExt].extractCmd.length == 0))
{
console.print("nchError: ncNo extract command is defined for " +
filenameExt + " files.\r\np");
console.print("\x01n\x01c\x01hError: \x01n\x01cNo extract command is defined for " +
filenameExt + " files.\r\n\x01p");
retObj.errorCode = 5;
return(retObj);
}
......@@ -642,26 +804,40 @@ function viewFile(pFilename, pWorkDir, pListFilesFunction)
if (workDirExists)
{
// Extract the archive into the work directory.
console.print("ncExtracting " + justFilename + "i...n\r\n");
console.print("\x01n\x01cExtracting " + justFilename + "\x01i...\x01n\r\n");
console.line_counter = 0; // To prevent pausing
extractArchive(pFilename, gViewableFileTypes[filenameExt].extractCmd, workDir);
var extractRet = extractArchive(pFilename, workDir);
if (extractRet.success)
{
// List the files.
var screenRow = pListFilesFunction(workDir, justFilename);
// Remove the work directory and all of its contents (and tell
// the user what we're doing).
console.print("n");
console.attributes = "N";
console.gotoxy(1, screenRow);
console.print("yhPerforming cleanup for " + justFilename + "i...n\r\n");
console.print("\x01y\x01hPerforming cleanup for " + justFilename + "\x01i...\x01n\r\n");
console.line_counter = 0; // To prevent pausing
}
else
{
console.crlf();
console.print("\x01n\x01h\x01y");
if (extractRet.error != "")
console.print(extractRet.error);
else
console.print("Failed to extract the archive");
console.attributes = "N";
console.crlf();
console.pause();
}
deltree(workDir);
}
else
{
console.clear("n");
console.print("nchNote: ncCould not create the temporary work directory for\r\n" +
justFilename + ", so only a basic view is provided.\r\np");
console.clear("\x01n");
console.print("\x01n\x01c\x01hNote: \x01n\x01cCould not create the temporary work directory for\r\n" +
justFilename + ", so only a basic view is provided.\r\n\x01p");
viewUsingVIEWCmd(pFilename, filenameExt);
retObj.errorCode = 7;
}
......@@ -686,7 +862,8 @@ function viewUsingVIEWCmd(pFilename, pFilenameExt)
var outputArray = execCmdWithOutput(viewCmd);
if (outputArray.length > 0)
{
console.print("n\r\n");
console.attributes = "N";
console.crlf();
var numLinesOutput = 1; // To test for outputting a pageful of lines
var pageSize = console.screen_rows - 1;
......@@ -710,8 +887,8 @@ function viewUsingVIEWCmd(pFilename, pFilenameExt)
// Prompt the user to continue. If they say yes, then
// reset the color back to normal. Otherwise, break from
// the input loop.
if (console.yesno("cContinue"))
console.print("n");
if (console.yesno("\x01cContinue"))
console.attributes = "N";
else
break;
}
......@@ -722,7 +899,7 @@ function viewUsingVIEWCmd(pFilename, pFilenameExt)
console.pause();
}
else
console.print("ncThe file is empty.");
console.print("\x01n\x01cThe file is empty.\x01n");
}
// Shows the user the list of files in a given directory (traditional
......@@ -735,30 +912,6 @@ function viewUsingVIEWCmd(pFilename, pFilenameExt)
// Return value: The screen row that's one past the last file listed.
function listFiles_Traditional(pDir, pArchiveFilename)
{
var onePastLastFileRow = console.screen_rows;
// Get a list of files in the directory
var files = directory(pDir + "*");
if (files.length > 0)
{
// This object will keep track of which filenames have had their
// slashes fixed.
var fileSlashesFixed = new Object();
// Screen display and array index variables
const listTopRow = 4;
const listBottomRow = console.screen_rows - 1;
const numPageLines = listBottomRow - listTopRow + 1; // # of lines in a page
var topFileIndex = 0; // The index of the array entry at the top of the screen
// Calculate the index of the filename that appears at the top of the
// last page.
var lastPageTopIndex = numPageLines;
while (lastPageTopIndex < files.length)
lastPageTopIndex += numPageLines;
lastPageTopIndex -= numPageLines;
// lastPageRow will store the row number of the last file displayed on the screen.
var lastPageRow = listBottomRow;
// This function goes to the next page. Returns whether or not
// to redraw (i.e., we won't want to redraw if there is no next
// page).
......@@ -798,11 +951,34 @@ function listFiles_Traditional(pDir, pArchiveFilename)
onePastLastFileRow = lastPageRow + 1;
}
var onePastLastFileRow = console.screen_rows;
// Get a list of files in the directory
var files = directory(pDir + "*");
if (files.length > 0)
{
// This object will keep track of which filenames have had their
// slashes fixed.
var fileSlashesFixed = {};
// Screen display and array index variables
const listTopRow = 4;
const listBottomRow = console.screen_rows - 1;
const numPageLines = listBottomRow - listTopRow + 1; // # of lines in a page
var topFileIndex = 0; // The index of the array entry at the top of the screen
// Calculate the index of the filename that appears at the top of the
// last page.
var lastPageTopIndex = numPageLines;
while (lastPageTopIndex < files.length)
lastPageTopIndex += numPageLines;
lastPageTopIndex -= numPageLines;
// lastPageRow will store the row number of the last file displayed on the screen.
var lastPageRow = listBottomRow;
// Start listing the file information.
// Output the file list headers.
console.clear("n");
console.clear("\x01n");
console.gotoxy(1, 1);
writeFileListHeader(pArchiveFilename);
......@@ -832,7 +1008,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
if (userInput.length == 0)
{
// Display a message and exit.
console.print("n\r\nyhInput timeout reached.");
console.print("\x01n\r\n\x01y\x01hInput timeout reached.\x01n");
mswait(2500);
continueOn = false;
}
......@@ -849,9 +1025,8 @@ function listFiles_Traditional(pDir, pArchiveFilename)
if (retObj.arrayIndex > -1)
fileSlashesFixed[retObj.arrayIndex] = true;
// Refresh the headers on the screen.
if (gANSISupported)
{
console.clear("n");
if (gANSISupported) {
console.clear("\x01n");
console.gotoxy(1, 1);
writeFileListHeader(pArchiveFilename);
}
......@@ -864,12 +1039,10 @@ function listFiles_Traditional(pDir, pArchiveFilename)
// If there is less than a pageful of file entries on this
// new page, then we need to erase the bottom row of the
// screen where the input prompt line was.
if (gANSISupported && (lastPageRow < listBottomRow))
{
if (gANSISupported && (lastPageRow < listBottomRow)) {
console.gotoxy(1, console.screen_rows);
console.clearline("n");
}
else
console.clearline("\x01n");
} else
console.crlf();
}
// P: Previous page
......@@ -904,7 +1077,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
if (gANSISupported && (lastPageRow < listBottomRow))
{
console.gotoxy(1, console.screen_rows);
console.clearline("n");
console.clearline("\x01n");
}
}
else
......@@ -916,7 +1089,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
if (gANSISupported)
console.crlf();
// Prompt the user for a file number.
console.print("ncFile #: h");
console.print("\x01n\x01cFile #: \x01h");
userInput = console.getnum(files.length);
if (userInput > 0)
{
......@@ -925,19 +1098,18 @@ function listFiles_Traditional(pDir, pArchiveFilename)
// Otherwise, let the user download the file.
if (file_isdir(files[index]))
{
console.print("nwhCan't download an entire directory.");
console.print("\x01n\x01w\x01hCan't download an entire directory.");
mswait(1500);
}
else
{
// Confirm with the user whether to download the file
var filename = getFilenameFromPath(files[index]);
var confirmText = "ncDownload h"
+ filename.substr(0, console.screen_columns-12) + "n";
var confirmText = "\x01n\x01cDownload \x01h"
+ filename.substr(0, console.screen_columns - 12) + "\x01n";
if (console.yesno(confirmText))
{
bbs.log_str(user.alias + " is downloading a file from an archive: " +
files[index]);
bbs.log_str(user.alias + " is downloading a file from an archive: " + files[index]);
bbs.send_file(files[index]);
}
}
......@@ -946,7 +1118,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
// Refresh the screen by outputting the file list headers.
if (gANSISupported)
{
console.clear("n");
console.clear("\x01n");
console.gotoxy(1, 1);
writeFileListHeader(pArchiveFilename);
}
......@@ -957,7 +1129,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
if (gANSISupported)
console.crlf();
// Prompt the user for a file number.
console.print("ncFile #: h");
console.print("\x01n\x01cFile #: \x01h");
userInput = console.getnum(files.length);
if (userInput > 0)
{
......@@ -971,8 +1143,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
// Confirm with the user whether to view the file.
var filename = getFilenameFromPath(files[index]);
var confirmText = "ncView h"
+ filename.substr(0, console.screen_columns-15) + "n";
var confirmText = "\x01n\x01cView \x01h" + filename.substr(0, console.screen_columns - 15) + "\x01n";
if (console.yesno(confirmText))
{
// If the entry is a directory, then call this function again
......@@ -990,7 +1161,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
// Refresh the screen by outputting the file list headers.
if (gANSISupported)
{
console.clear("n");
console.clear("\x01n");
console.gotoxy(1, 1);
writeFileListHeader(pArchiveFilename);
}
......@@ -1008,7 +1179,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
// Refresh the screen by outputting the file list headers.
if (gANSISupported)
{
console.clear("n");
console.clear("\x01n");
console.gotoxy(1, 1);
writeFileListHeader(pArchiveFilename);
}
......@@ -1016,7 +1187,7 @@ function listFiles_Traditional(pDir, pArchiveFilename)
}
}
else
console.print("ncCould not extract/view the file, or it is empty.\r\np");
console.print("\x01n\x01cCould not extract/view the file, or it is empty.\r\n\x01p");
return onePastLastFileRow;
}
......@@ -1036,10 +1207,12 @@ 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);
// Add line characters to the end of the screen.
for (var x = 30; x < console.screen_columns - 2; ++x)
writeFileListHeader.topHelp3 += "Ä";
//for (var x = 30; x < console.screen_columns - 2; ++x)
// writeFileListHeader.topHelp3 += HORIZONTAL_SINGLE;
writeFileListHeader.topHelp3 += "\r\n";
}
......@@ -1069,14 +1242,15 @@ function writeFileListHeader(pFilename)
function doFileNumInput(pFileArray, pDir, pListFilesFunction, pFileNum)
{
// Create the return object
var retObj = new Object();
retObj.fileNum = (pFileNum == undefined ? -1 : pFileNum);
retObj.arrayIndex = (pFileNum == undefined ? -1 : pFileNum-1);
var retObj = {
fileNum: (pFileNum == undefined ? -1 : pFileNum),
arrayIndex: (pFileNum == undefined ? -1 : pFileNum-1)
};
// Create a persistent object to keep track of the indexes of the files
// in the array that have had their slashes fixed.
if (doFileNumInput.fileSlashesFixed == undefined)
doFileNumInput.fileSlashesFixed = new Object();
doFileNumInput.fileSlashesFixed = {};
var userInput = 0;
// If pFileNum wasn't passed in, then prompt the user for the file
......@@ -1104,12 +1278,12 @@ function doFileNumInput(pFileArray, pDir, pListFilesFunction, pFileNum)
userInput = "V";
else
{
console.print("nch" +
console.print("\x01n\x01c\x01h" +
justFilename.substr(0, console.screen_columns-1));
console.crlf();
console.print("y(cVy)nciewbh, " +
"y(cDy)ncownloadbh, or " +
"y(cCy)ncancel: h");
console.print("\x01y(\x01cV\x01y)\x01n\x01ciew\x01b\x01h, " +
"\x01y(\x01cD\x01y)\x01n\x01cownload\x01b\x01h, or " +
"\x01y(\x01cC\x01y)\x01n\x01cancel: \x01h");
userInput = console.getkeys("VDC").toString();
}
if (userInput == "V")
......@@ -1133,7 +1307,7 @@ function doFileNumInput(pFileArray, pDir, pListFilesFunction, pFileNum)
// Otherwise, let the user download the file.
if (file_isdir(pFileArray[retObj.arrayIndex]))
{
console.print("nwhCan't download an entire directory.");
console.print("\x01n\x01w\x01hCan't download an entire directory.\x01n");
mswait(1500);
}
else
......@@ -1154,11 +1328,11 @@ function writeCmdPrompt_Traditional()
// Construct the prompt text only once (for speed).
if (writeCmdPrompt_Traditional.text == undefined)
{
writeCmdPrompt_Traditional.text = "nyh(cNy)ncextbh, "
+ "yh(cPy)ncrevbh, yh(cFy)ncirstbh, "
+ "yh(cLy)ncastbh, yh(cVy)nciewbh, "
+ "yh(cDy)ncLbh, yh(cQy)ncuitbh, "
+ "c#b, or c?nc: h";
writeCmdPrompt_Traditional.text = "\x01n\x01y\x01h(\x01cN\x01y)\x01n\x01cext\x01b\x01h, "
+ "\x01y\x01h(\x01cP\x01y)\x01n\x01crev\x01b\x01h, \x01y\x01h(\x01cF\x01y)\x01n\x01cirst\x01b\x01h, "
+ "\x01y\x01h(\x01cL\x01y)\x01n\x01cast\x01b\x01h, \x01y\x01h(\x01cV\x01y)\x01n\x01ciew\x01b\x01h, "
+ "\x01y\x01h(\x01cD\x01y)\x01n\x01cL\x01b\x01h, \x01y\x01h(\x01cQ\x01y)\x01n\x01cuit\x01b\x01h, "
+ "\x01c#\x01b, or \x01c?\x01n\x01c: \x01h";
}
console.print(writeCmdPrompt_Traditional.text);
}
......@@ -1173,36 +1347,6 @@ function writeCmdPrompt_Traditional()
// Return value: The screen row that's one past the last file listed.
function listFiles_Lightbar(pDir, pArchiveFilename)
{
var onePastLastFileRow = console.screen_rows;
// Get a list of files in the directory
var files = directory(pDir + "*");
if (files.length > 0)
{
// This object will keep track of which filenames have had their
// slashes fixed.
var fileSlashesFixed = new Object();
// Screen row and array index variables
const listTopRow = 4;
const listBottomRow = console.screen_rows - 1;
const numPageLines = listBottomRow - listTopRow + 1; // # of lines in a page
var topFileIndex = 0; // Index of the file appearing at the top of the screen
var selectedIndex = 0; // The index of the currently selected file
onePastLastFileRow = listTopRow + (files.length-topFileIndex);
// Set up a cursor position object, which will start at the top row.
var curpos = new Object();
curpos.x = 1;
curpos.y = listTopRow;
// Calculate the index of the filename that appears at the top of the
// last page.
var lastPageTopIndex = numPageLines;
while (lastPageTopIndex < files.length)
lastPageTopIndex += numPageLines;
lastPageTopIndex -= numPageLines;
// This function goes to the next page. Returns whether or not
// to redraw (i.e., we won't want to redraw if there is no next
// page).
......@@ -1237,13 +1381,43 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
return redraw;
}
var onePastLastFileRow = console.screen_rows;
// Get a list of files in the directory
var files = directory(pDir + "*");
if (files.length > 0)
{
// This object will keep track of which filenames have had their
// slashes fixed.
var fileSlashesFixed = {};
// Screen row and array index variables
const listTopRow = 4;
const listBottomRow = console.screen_rows - 1;
const numPageLines = listBottomRow - listTopRow + 1; // # of lines in a page
var topFileIndex = 0; // Index of the file appearing at the top of the screen
var selectedIndex = 0; // The index of the currently selected file
onePastLastFileRow = listTopRow + (files.length - topFileIndex);
// Set up a cursor position object, which will start at the top row.
var curpos = {
x: 1,
y: listTopRow
};
// Calculate the index of the filename that appears at the top of the
// last page.
var lastPageTopIndex = numPageLines;
while (lastPageTopIndex < files.length)
lastPageTopIndex += numPageLines;
lastPageTopIndex -= numPageLines;
// Draw the header lines and the help line at the bottom
drawTopAndBottom_Lightbar(pArchiveFilename);
// Now, output the first page of information, move the cursor up to the top,
// and start the input loop.
listFiles_ShowScreenful(files, topFileIndex, listTopRow, listBottomRow, topFileIndex,
false, true);
listFiles_ShowScreenful(files, topFileIndex, listTopRow, listBottomRow, topFileIndex, false, true);
var userInput = "";
var continueOn = true;
while (continueOn)
......@@ -1256,8 +1430,8 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
{
// Display a message and exit.
console.gotoxy(1, console.screen_rows);
console.clearline("n");
console.print("nyhInput timeout reached.");
console.clearline("\x01n");
console.print("\x01n\x01y\x01hInput timeout reached.");
mswait(2500);
continueOn = false;
}
......@@ -1289,8 +1463,7 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
// Move the selection to the bottom of the list, then refresh the screen.
selectedIndex = topFileIndex + numPageLines - 1;
curpos.y = listBottomRow;
listFiles_ShowScreenful(files, topFileIndex, listTopRow, listBottomRow,
selectedIndex, true, true);
listFiles_ShowScreenful(files, topFileIndex, listTopRow, listBottomRow, selectedIndex, true, true);
}
}
}
......@@ -1319,10 +1492,7 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
// Note: curpos is updated by goToNextPage(), so we don't have to
// update it here.
if (goToNextPage())
{
listFiles_ShowScreenful(files, topFileIndex, listTopRow, listBottomRow,
selectedIndex, true, true);
}
listFiles_ShowScreenful(files, topFileIndex, listTopRow, listBottomRow, selectedIndex, true, true);
}
}
}
......@@ -1372,7 +1542,7 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
{
// Place the cursor at the desired location and do file # input.
console.gotoxy(1, console.screen_rows);
console.clearline("n");
console.clearline("\x01n");
var retObj = doFileNumInput(files, pDir, listFiles_Lightbar, selectedIndex + 1);
// doFileNumInput() fixes file path slashes for the chosen file,
// so if the user chose a file, then update fileSlashesFixed
......@@ -1400,13 +1570,13 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
}
// Go to the last line on the screen (for prompting/messages)
console.gotoxy(1, console.screen_rows);
console.clearline("n");
console.clearline("\x01n");
// If the entry is a directory, then report an error. Otherwise,
// go to the bottom and confirm with the user if they really
// want to download the file.
if (file_isdir(files[selectedIndex]))
{
console.print("nwhCan't download an entire directory.");
console.print("\x01n\x01w\x01hCan't download an entire directory.");
mswait(1500);
// Re-draw the bottom help line
console.gotoxy(1, console.screen_rows);
......@@ -1416,9 +1586,9 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
{
var justFilename = getFilenameFromPath(files[selectedIndex]);
var filenameWidth = console.screen_columns - 23;
if (console.yesno("ncAdd h" +
if (console.yesno("\x01n\x01cAdd \x01h" +
justFilename.substr(0, filenameWidth) +
"nc to batch DL queue"))
"\x01n\x01c to batch DL queue"))
{
// Create the temporary batch download directory and copy
// the selected file to it. If that succeeded, then add
......@@ -1429,12 +1599,12 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
{
// Add the file to the DL queue. If failed, show an error.
console.gotoxy(1, console.screen_rows);
console.clearline("n");
console.clearline("\x01n");
if (addFileToBatchQueue(DLFilename))
console.print("ncFile added to batch DL queue.");
console.print("\x01n\x01cFile added to batch DL queue.");
else
{
console.print("nyhUnable to add to batch DL queue!");
console.print("\x01n\x01y\x01hUnable to add to batch DL queue!");
file_remove(DLFilename);
}
mswait(1500);
......@@ -1443,8 +1613,8 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
{
// Couldn't copy the file to the temporary DL queue directory.
console.gotoxy(1, console.screen_rows);
console.clearline("n");
console.print("nyhUnable to copy to queue directory!");
console.clearline("\x01n");
console.print("\x01n\x01y\x01hUnable to copy to queue directory!");
mswait(1500);
}
}
......@@ -1457,17 +1627,16 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
}
*/
// D: Download the selected file
else if (userInput == "D")
{
else if (userInput == "D") {
// Go to the last line on the screen (for prompting/messages)
console.gotoxy(1, console.screen_rows);
console.clearline("n");
console.clearline("\x01n");
// If the entry is a directory, then report an error. Otherwise,
// go to the bottom and confirm with the user if they really
// want to download the file.
if (file_isdir(files[selectedIndex]))
{
console.print("nwhCan't download an entire directory.");
console.print("\x01n\x01w\x01hCan't download an entire directory.");
mswait(1500);
// Re-draw the bottom help line
console.gotoxy(1, console.screen_rows);
......@@ -1476,10 +1645,9 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
else
{
var filenameWidth = console.screen_columns - 24;
if (console.yesno("ncDownload h" +
if (console.yesno("\x01n\x01cDownload \x01h" +
getFilenameFromPath(files[selectedIndex]).substr(0, filenameWidth) +
"nc: Are you sure"))
{
"\x01n\x01c: Are you sure")) {
bbs.log_str(user.alias + " is downloading a file from an archive: " +
files[selectedIndex]);
bbs.send_file(files[selectedIndex]);
......@@ -1492,8 +1660,7 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
}
}
// Q or ESC key: Quit
else if ((userInput == "Q") || (userInput == ESC_KEY))
{
else if ((userInput == "Q") || (userInput == ESC_KEY)) {
continueOn = false;
break;
}
......@@ -1526,9 +1693,9 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
else
{
console.gotoxy(1, console.screen_rows);
console.clearline("n");
var confirmText = "ncView h"
+ filename.substr(0, console.screen_columns-15) + "n"
console.clearline("\x01n");
var confirmText = "\x01n\x01cView \x01h"
+ filename.substr(0, console.screen_columns - 15) + "\x01n"
viewIt = console.yesno(confirmText);
}
if (viewIt)
......@@ -1605,8 +1772,8 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
// be used for getting the rest of the message number.
console.ungetstr(userInput);
console.gotoxy(1, console.screen_rows);
console.clearline("n");
console.print("cFile #: h");
console.clearline("\x01n");
console.print("\x01cFile #: \x01h");
var retObj = doFileNumInput(files, pDir, listFiles_Lightbar);
// doFileNumInput() fixes file path slashes for the chosen file,
// so if the user chose a file, then update fileSlashesFixed
......@@ -1621,7 +1788,7 @@ function listFiles_Lightbar(pDir, pArchiveFilename)
}
}
else
console.print("ncCould not extract/view the file, or it is empty.\r\np");
console.print("\x01n\x01cCould not extract/view the file, or it is empty.\r\n\x01p");
return onePastLastFileRow;
}
......@@ -1632,12 +1799,12 @@ function displayBottomHelpLine_Lightbar()
// Construct the help text variable only once (for speed).
if (displayBottomHelpLine_Lightbar.bottomHelp == undefined)
{
displayBottomHelpLine_Lightbar.bottomHelp = "n7r"
+ UP_ARROW_DISPLAY + "b, r" + DOWN_ARROW_DISPLAY
+ "b, rHOMEb, rENDb, rENTERb, rNm)bext, "
+ "rPm)brev, rFm)birst, rLm)bast, "
+ "rVm)biew, rDm)bL, rQm)buit, "
+ "r#b, r? ";
displayBottomHelpLine_Lightbar.bottomHelp = "\x01n\x01" + "7\x01r"
+ UP_ARROW_DISPLAY + "\x01b, \x01r" + DOWN_ARROW_DISPLAY
+ "\x01b, \x01rHOME\x01b, \x01rEND\x01b, \x01rENTER\x01b, \x01rN\x01m)\x01bext, "
+ "\x01rP\x01m)\x01brev, \x01rF\x01m)\x01birst, \x01rL\x01m)\x01bast, "
+ "\x01rV\x01m)\x01biew, \x01rD\x01m)\x01bL, \x01rQ\x01m)\x01buit, "
+ "\x01r#\x01b, \x01r? ";
}
// Go to the last row on the screen and display the help line
......@@ -1653,7 +1820,7 @@ function drawTopAndBottom_Lightbar(pFilename)
{
// Clear the screen, display the help line at the bottom of the screen,
// and output the file list headers.
console.clear("n");
console.clear("\x01n");
displayBottomHelpLine_Lightbar();
console.gotoxy(1, 1);
writeFileListHeader(pFilename);
......@@ -1719,7 +1886,7 @@ function listFiles_ShowScreenful(pArray, pStartIndex, pStartLine, pEndLine, pHig
// end of the "screen".
if (clearToEOS && (screenLine < pEndLine))
{
console.print("n");
console.attributes = "N";
const onePastLastLine = console.screen_rows;
const clearWidth = console.screen_columns - 1;
const formatStr = "%" + clearWidth + "s";
......@@ -1752,7 +1919,7 @@ function writeFileInfo(pFilename, pHighlight, pFileNum)
}
if (writeFileInfo.formatStr == undefined)
{
writeFileInfo.formatStr = "n" + gGenConfig.colors.fileNums + "%4d "
writeFileInfo.formatStr = "\x01n" + gGenConfig.colors.fileNums + "%4d "
+ gGenConfig.colors.fileSize + "%" + sizeWidth + "s "
+ gGenConfig.colors.fileDate + "%-" + dateWidth + "s "
+ gGenConfig.colors.fileTime + "%-" + timeWidth
......@@ -1761,7 +1928,7 @@ function writeFileInfo(pFilename, pHighlight, pFileNum)
}
if (writeFileInfo.hiFormatStr == undefined)
{
writeFileInfo.hiFormatStr = "n" + gGenConfig.colors.highlightedFile + "%4d %"
writeFileInfo.hiFormatStr = "\x01n" + gGenConfig.colors.highlightedFile + "%4d %"
+ sizeWidth + "s %-" + dateWidth + "s %-" + timeWidth + "s %-"
+ writeFileInfo.filenameWidth + "s";
}
......@@ -1891,7 +2058,7 @@ function trimSpaces(pString, pLeading, pMultiple, pTrailing)
return pString;
}
// Returns a filename's extension. Always returns a string.
// Returns a filename's extension in uppercase. Always returns a string.
//
// Parameters:
// pFilename: The name of a file
......@@ -1915,26 +2082,6 @@ function getFilenameExtension(pFilename)
return filenameExt;
}
// Unit test function for getFilenameExtension()
function test_getFilenameExtension()
{
console.crlf();
if (getFilenameExtension("file.zip") != "ZIP")
console.print("nyhtest_getFilenameExtension(): Test 1 failed\r\n");
if (getFilenameExtension("file.7z") != "7Z")
console.print("nyhtest_getFilenameExtension(): Test 2 failed\r\n");
if (getFilenameExtension("file.tar.gz") != "TAR.GZ")
console.print("nyhtest_getFilenameExtension(): Test 3 failed\r\n");
if (getFilenameExtension("file") != "")
console.print("nyhtest_getFilenameExtension(): Test 4 failed\r\n");
if (getFilenameExtension("file.") != "")
console.print("nyhtest_getFilenameExtension(): Test 5 failed\r\n");
}
// This function returns just the filename from the end of a full path, regardless
// of whether it has a trailing slash.
//
......@@ -2043,43 +2190,6 @@ function fixPathSlashes(pPath)
return path;
}
// Unit test function for fixPathSlashes
function test_fixPathSlashes()
{
console.crlf();
// Windows tests
if (/^WIN/.test(system.platform.toUpperCase()))
{
if (fixPathSlashes("file.zip") != "file.zip")
console.print("nyhtest_fixPathSlashes(): Test 1 failed\r\n");
if (fixPathSlashes("D:\\path\\file.zip") != "D:\\path\\file.zip")
console.print("nyhtest_fixPathSlashes(): Test 2 failed\r\n");
if (fixPathSlashes("D:/path/file.zip") != "D:\\path\\file.zip")
console.print("nyhtest_fixPathSlashes(): Test 3 failed\r\n");
if (fixPathSlashes("D:/path\\file.zip") != "D:\\path\\file.zip")
console.print("nyhtest_fixPathSlashes(): Test 4 failed\r\n");
if (fixPathSlashes("\\path\\file.zip") != "\\path\\file.zip")
console.print("nyhtest_fixPathSlashes(): Test 5 failed\r\n");
if (fixPathSlashes("/path/file.zip") != "\\path\\file.zip")
console.print("nyhtest_fixPathSlashes(): Test 6 failed\r\n");
if (fixPathSlashes("/path\\file.zip") != "\\path\\file.zip")
console.print("nyhtest_fixPathSlashes(): Test 6 failed\r\n");
if (fixPathSlashes("\\path/file.zip") != "\\path\\file.zip")
console.print("nyhtest_fixPathSlashes(): Test 5 failed\r\n");
}
// *nix tests
else
{
}
}
// Adds a file to the user's batch download queue. Returns true on
// success or false on failure.
// Note: Despite my hopes, this doesn't work, because a file needs
......@@ -2125,7 +2235,7 @@ function showHelpScreen(pLightbarMode)
var width = gDDArcViewerProgName.length + 2;
showHelpScreen.progInfoHeader = new Array();
// Upper & lower border lines
showHelpScreen.progInfoHeader[0] = "ch" + UPPER_LEFT_SINGLE;
showHelpScreen.progInfoHeader[0] = "\x01c\x01h" + UPPER_LEFT_SINGLE;
showHelpScreen.progInfoHeader[2] = LOWER_LEFT_SINGLE;
for (var i = 0; i < width; ++i)
{
......@@ -2135,28 +2245,29 @@ function showHelpScreen(pLightbarMode)
showHelpScreen.progInfoHeader[0] += UPPER_RIGHT_SINGLE;
showHelpScreen.progInfoHeader[2] += LOWER_RIGHT_SINGLE;
// Middle section with the program name
showHelpScreen.progInfoHeader[1] = VERTICAL_SINGLE + "4yh "
+ gDDArcViewerProgName + " nch" + VERTICAL_SINGLE;
showHelpScreen.progInfoHeader[1] = VERTICAL_SINGLE + "\x01" + "4\x01y\x01h "
+ gDDArcViewerProgName + " \x01n\x01c\x01h" + VERTICAL_SINGLE;
// Version & author information
showHelpScreen.progInfoHeader[3] = "ncVersion g" + gDDArcViewerVersion
+ " wh(b" + gDDArcViewerVerDate + "w)";
showHelpScreen.progInfoHeader[4] = "ncby Eric Oulashin h(ncsysop of Digital Distortion BBSh)";
showHelpScreen.progInfoHeader[3] = "\x01n\x01cVersion \x01g" + gDDArcViewerVersion
+ " \x01w\x01h(\x01b" + gDDArcViewerVerDate + "\x01w)";
showHelpScreen.progInfoHeader[4] = "\x01n\x01cby Eric Oulashin \x01h(\x01n\x01csysop of Digital Distortion BBS\x01h)";
}
// Display the header lines
console.clear("n");
console.clear("\x01n");
for (var i = 0; i < showHelpScreen.progInfoHeader.length; ++i)
console.center(showHelpScreen.progInfoHeader[i]);
// Display the program help
console.crlf();
console.print("nc" + gDDArcViewerProgName + " lets you list the files inside an archive.\r\n");
console.print("\x01n\x01c" + gDDArcViewerProgName + " lets you list the files inside an archive.\r\n");
console.print("You can also view or download the files from the archive.");
console.crlf();
console.crlf();
console.print("The following is a list of the command keys:\r\n");
console.print("khÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r\n");
var formatStr = "nch%5sg: nc%s\r\n";
console.print("\x01k\x01h" + charStr(HORIZONTAL_SINGLE, 44));
console.crlf();
var formatStr = "\x01n\x01c\x01h%5s\x01g: \x01n\x01c%s\r\n";
if (pLightbarMode)
{
printf(formatStr, "HOME", "Go to the first file on the page");
......@@ -2181,7 +2292,7 @@ function showHelpScreen(pLightbarMode)
}
printf(formatStr, "Q/ESC", "Quit");
console.crlf();
console.print("ncYou can also choose a file to view/download by typing its number.");
console.print("\x01n\x01cYou can also choose a file to view/download by typing its number.");
console.crlf();
if (!gANSISupported)
console.crlf();
......@@ -2196,12 +2307,34 @@ function showHelpScreen(pLightbarMode)
// arguments with spaces in them are a single argument. This function
// was written by Tracker1 of The Roughnecks BBS - He posted the code
// in the DOVE-Net Synchronet Discussion sub-board on December 20, 2009.
function fixArgs(input)
function fixArgs(argv)
{
// If there is only one element, then just return that back to the caller.
if (argv.length == 1)
return [ argv[0] ];
var patt1 = /\"[^\"]*\"|\S+/g;
var patt2 = /^\"?([^\"]*)\"?$/;
return input.join(' ').match(patt1).map(function(item)
return argv.join(' ').match(patt1).map(function(item)
{
return item.replace(patt2, "$1")
});
}
// Returns a string with a character repeated a given number of times
//
// Parameters:
// pChar: The character to repeat in the string
// pNumTimes: The number of times to repeat the character
//
// Return value: A string with the given character repeated the given number of times
function charStr(pChar, pNumTimes)
{
if (typeof(pChar) !== "string" || pChar.length == 0 || typeof(pNumTimes) !== "number" || pNumTimes < 1)
return "";
var str = "";
for (var i = 0; i < pNumTimes; ++i)
str += pChar;
return str;
}
\ No newline at end of file
......@@ -22,6 +22,11 @@
* directory is removed.
*/
"use strict";
if (typeof(require) === "function")
require("sbbsdefs.js", "K_UPPER");
else
load("sbbsdefs.js");
// Remove the Digital Distortion Archive Viewer work directory and
......@@ -42,9 +47,7 @@ file_remove(system.node_dir + "DDArcViewer_DLList.txt");
// Return value: Boolean - Whether or not the directory was removed.
function deltree(pDir)
{
if ((pDir == null) || (pDir == undefined))
return false;
if (typeof(pDir) != "string")
if (typeof(pDir) !== "string")
return false;
if (pDir.length == 0)
return false;
......
; Compressed archive file extensions
[ZIP]
; PKZip for Win32
;VIEW=\BBS\COMPRESS\pkzip25.exe -view -NoZipExtension %FILENAME%
;EXTRACT=\BBS\COMPRESS\pkzip25.exe -extract -NoZipExtension -Directories %FILENAME% %FILESPEC% %TO_DIR%
; Info-ZIP for Win32 console (comes with Synchronet)
VIEW=\BBS\sbbs\exec\unzip.exe -l %FILENAME%
EXTRACT=\BBS\sbbs\exec\unzip.exe -qq -o %FILENAME% %FILESPEC% -d %TO_DIR%
; Info-ZIP, *nix
;VIEW=unzip -l %FILENAME%
;EXTRACT=unzip -qq -o %FILENAME% %FILESPEC% -d %TO_DIR%
; 7-Zip for Win32 console
;VIEW=\BBS\COMPRESS\7za.exe l %FILENAME%
;EXTRACT=\BBS\COMPRESS\7za.exe x -y %FILENAME% %FILESPEC% -o%TO_DIR%
VIEW=unzip -l %FILENAME%
EXTRACT=unzip -qq -o %FILENAME% %FILESPEC% -d %TO_DIR%
; 7-Zip for *nix
;VIEW=7za l %FILENAME%
;EXTRACT=7za x -y %FILENAME% %FILESPEC% -o%TO_DIR%
;VIEW=7z l %FILENAME%
;EXTRACT=7z x -y -pxyz %FILENAME% %FILESPEC% -o%TO_DIR%
[7Z]
; 7-Zip for Win32 console
VIEW=\BBS\COMPRESS\7za.exe l %FILENAME%
EXTRACT=\BBS\COMPRESS\7za.exe x -y %FILENAME% %FILESPEC% -o%TO_DIR%
; 7-Zip for *nix
;VIEW=7za l %FILENAME%
;EXTRACT=7za x -y %FILENAME% %FILESPEC% -o%TO_DIR%
VIEW=7z l %FILENAME%
EXTRACT=7z x -y -pxyz %FILENAME% %FILESPEC% -o%TO_DIR%
[RAR]
; RAR for Win32 console
VIEW=\BBS\COMPRESS\Rar.exe lt %FILENAME%
EXTRACT=\BBS\COMPRESS\Rar.exe x %FILENAME% %FILESPEC% %TO_DIR%
VIEW=rar lt %FILENAME%
EXTRACT=rar x -p- -y %FILENAME% %FILESPEC% %TO_DIR%
; Alexander Roshal's unrar for *nix
;VIEW=unrar lt %FILENAME%
;EXTRACT=unrar x %FILENAME% %FILESPEC% %TO_DIR%
[ARJ]
; ARJ for Win32 console
VIEW=\BBS\COMPRESS\ARJ32.EXE l %FILENAME%
EXTRACT=\BBS\COMPRESS\ARJ32.EXE x %FILENAME% %FILESPEC% -ht%TO_DIR%
; Open-Source ARJ for *nix
;VIEW=arj l %FILENAME%
;EXTRACT=arj x %FILENAME% %FILESPEC% -ht%TO_DIR%
VIEW=arj l %FILENAME%
EXTRACT=arj x %FILENAME% %FILESPEC% -ht%TO_DIR%
[ISO]
; 7-Zip for Win32 console
VIEW=\BBS\COMPRESS\7za.exe l %FILENAME%
EXTRACT=\BBS\COMPRESS\7za.exe x -y %FILENAME% %FILESPEC% -o%TO_DIR%
; 7-Zip for *nix
;VIEW=7za l %FILENAME%
;EXTRACT=7za x -y %FILENAME% %FILESPEC% -o%TO_DIR%
VIEW=7z l %FILENAME%
EXTRACT=7z x -y %FILENAME% %FILESPEC% -o%TO_DIR%
[TAR]
; 7-Zip for Win32 console
VIEW=\BBS\COMPRESS\7za.exe l %FILENAME%
EXTRACT=\BBS\COMPRESS\7za.exe x -y %FILENAME% %FILESPEC% -o%TO_DIR%
; 7-Zip for *nix
;VIEW=7za l %FILENAME%
;EXTRACT=7za x -y %FILENAME% %FILESPEC% -o%TO_DIR%
VIEW=7z l %FILENAME%
EXTRACT=7z x -y -pxyz %FILENAME% %FILESPEC% -o%TO_DIR%
[GZ]
; 7-Zip for Win32 console
VIEW=\BBS\COMPRESS\7za.exe l %FILENAME%
EXTRACT=\BBS\COMPRESS\7za.exe x -y %FILENAME% %FILESPEC% -o%TO_DIR%
; 7-Zip for *nix
;VIEW=7za l %FILENAME%
;EXTRACT=7za x -y %FILENAME% %FILESPEC% -o%TO_DIR%
VIEW=7z l %FILENAME%
EXTRACT=7z x -y -pxyz %FILENAME% %FILESPEC% -o%TO_DIR%
[TGZ]
; gzip for Win32 cmmand-line
;VIEW=\BBS\COMPRESS\gzip.exe -l %FILENAME%
; 7-Zip for Win32 console
VIEW=\BBS\COMPRESS\7za.exe l %FILENAME%
EXTRACT=\BBS\COMPRESS\7za.exe x -y %FILENAME% %FILESPEC% -o%TO_DIR%
; 7-Zip for *nix
;VIEW=7za l %FILENAME%
;EXTRACT=7za x -y %FILENAME% %FILESPEC% -o%TO_DIR%
VIEW=7z l %FILENAME%
EXTRACT=7z x -y -pxyz %FILENAME% %FILESPEC% -o%TO_DIR%
[TAR.GZ]
; 7-Zip for Win32 console
VIEW=\BBS\COMPRESS\7za.exe l %FILENAME%
EXTRACT=\BBS\COMPRESS\7za.exe x -y %FILENAME% %FILESPEC% -o%TO_DIR%
; tar for *nix
;VIEW=tar ztvf %FILENAME%
;EXTRACT=cd %TO_DIR% && tar zxvf %FILENAME%
VIEW=tar ztvf %FILENAME%
EXTRACT=cd %TO_DIR% && tar zxvf %FILENAME%
; Microsoft Installer file
[MSI]
; 7-Zip for *nix
VIEW=7z l %FILENAME%
EXTRACT=7z x -y -pxyz %FILENAME% %FILESPEC% -o%TO_DIR%
; Text file extensions
[TXT]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[TEXT]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[DIZ]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[DOC]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[ANS]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[ASC]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[ASCII]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[RIP]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[NFO]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Chinese text file
[ZW]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[NEW]
IsText=Yes
; *nix
VIEW=cat %FILENAME%
[BBS]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[ICE]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[LOG]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Guitar tab file
[TAB]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Guitar tab file
[CRD]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Guitar tab file
[CHORD]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
[NEW]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Readme file (i.e., READ.ME)
[ME]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[FAQ]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[NOW]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[HTM]
IsText=Yes
......@@ -238,269 +171,201 @@ VIEW=?typehtml -color %FILENAME%
[REG]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; A readme file, as in README.1ST
[1ST]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[CFG]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
[INI]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Batch file
[BAT]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Command lst file (similar to a DOS batch file)
[CMD]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; REXX script (a programming language developed by IBM)
[REXX]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; *nix shell script
[SH]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Outlook Express email message
[EMAIL]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Mail message
[EMLX]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; EditPad Pro
[EPP]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Error log
[ERR]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Outlook Express mailbox index file
[IDX]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Data list
[LST]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Mailbox message file
[MSG]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; JavaScript source file
[JS]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Perl source file
[PL]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Python source file
[PY]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; PHP source file
[PHP]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; C source file
[C]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; C++ source file
[CPP]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; C++ source file
[CXX]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; C++ source file
[C++]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Header file for C/C++/Objective-C/etc.
[H]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; C++ header file
[HPP]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Objective-C source file
[M]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Objective-C with C++ source file
[MM]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; C# source file
[CS]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Pascal source file
[PAS]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; BASIC source file
[BAS]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Visual Basic source file
[VB]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Common Gateway Interface script
[CGI]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Include file
[INC]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
VIEW=cat %FILENAME%
; Baja source file (for Synchronet scripts)
[SRC]
IsText=Yes
; Windows
VIEW=type %FILENAME%
; *nix
;VIEW=cat %FILENAME%
\ No newline at end of file
:VIEW=cat %FILENAME%
\ No newline at end of file
Digital Distortion Archive Viewer
Version 1.03
Release date: 2009-12-20
Version 1.04
Release date: 2022-05-16
by
Eric Oulashin
Sysop of Digital Distortion BBS
BBS internet address: digitaldistortionbbs.com
digdist.bbsindex.com
digdist.synchro.net
Email: eric.oulashin@gmail.com
......@@ -18,7 +18,7 @@ Contents
========
1. Disclaimer
2. Introduction
3. Archive File Software
3. Archive Formats
4. Installation and Setup
5. Main configuration file
6. Archive file type configuration file
......@@ -77,8 +77,16 @@ queue. The reason is that Synchronet won't add files to the user's
download queue unless the file is in Synchronet's file database.
3. Archive File Software
========================
3. Archive Formats
==================
If your BBS is running Synchronet 3.19 or newer, Digital Distortion Archive
Viewer makes use of the built-in archive support in Synchronet for fast
extraction (it supports zip, 7z, tgz, etc.). You can also configure archiver
commands to extract other formats if you want. If your version of Synchronet
3.18 or below, then you will need to configure archiver extraction commands for
all archive file types you want to support.
Digital Distortion Archive Viewer comes with configurations to handle
ZIP, 7Z (7-Zip), RAR, ARJ, TAR, GZ, TGZ, and TAR.GZ archives, and many
text file formats.
......@@ -87,30 +95,30 @@ The file format configuration file included with this script includes
VIEW and EXTRACT command lines for various archivers for both Windows
and Linux. In order for this script to work properly, you will need
to make sure you have the appropriate archiver software installed on
your system, and you will need to edit the DDArcViewerFileTypes.cfg
your system, and you will need to edit the dd_arc_viewer_file_types.cfg
file (using a text editor) and make sure you have the VIEW and
EXTRACT command lines set properly for your archiver software.
The included DDArcViewerFileTypes.cfg file has command lines for
The included dd_arc_viewer_file_types.cfg file has command lines for
Windows and Linux, and the Linux command lines are commented out.
For information on that configuration file, see section 6: Archive
file type configuration file.
The following archive contains Win32 command-line archivers for popular
archive file formats:
http://digdist.bbsindex.com/miscFilesForDL/Win32CmdLineCompressionTools.zip
http://digdist.synchro.net/miscFilesForDL/Win32CmdLineCompressionTools.zip
The archivers included in that archive handle the most popular file formats
(ZIP, 7Z (7-Zip), RAR, ARJ, TAR, GZ, TGZ, and TAR.GZ), and they are set up in
DDArcViewerFileTypes.cfg. If your BBS is running in Windows, the included
dd_arc_viewer_file_types.cfg. If your BBS is running in Windows, the included
configuration file should work for you - But note that you will need to edit
the DDArcViewerFileTypes.cfg file and change the paths to the .exe files
the dd_arc_viewer_file_types.cfg file and change the paths to the .exe files
according to where you copied them to your system. If you are running Linux,
that .cfg file also has the Linux command lines as comments).
If you copy the archivers to a directory that is not in your system path, you
will need to edit the DDArcViewerFileTypes.cfg file to include the full paths
will need to edit the dd_arc_viewer_file_types.cfg file to include the full paths
with the archive executables.
The configuration file DDArcViewerFileTypes.cfg includes a setup
The configuration file dd_arc_viewer_file_types.cfg includes a setup
for using 7-Zip to extract ISO (CD/DVD image) files; however, in
testing, it seemed that 7-Zip can only extract or see one file in
an ISO image.
......@@ -163,16 +171,17 @@ Step 1: Copy the script files, configuration files, & archivers to your system
Digital Distortion Archive Viewer consists of the following 4 files, which
you will need to place in your sbbs/exec directory (or another directory of
your choice):
1. DDArcViewer.js
2. DDArcViewerCleanup.js
3. DDArcViewer.cfg
4. DDArcViewerFileTypes.cfg
1. dd_arc_viewer.js
2. dd_arc_viewer_cleanup.js
3. dd_arc_viewer.cfg
4. dd_arc_viewer_file_types.cfg
These files must be all together in the same directory.
For sysops running their BBS in Windows, the following archiver programs
in the Win32Archivers directory will need to be placed in a directory
(preferably a directory that's included in the system's path):
For sysops running their BBS in Windows using Synchronet 3.18 or below, the
following archiver programs in the Win32Archivers directory will need to be
placed in a directory (preferably a directory that's included in the system's
path):
1. 7za.exe
2. ARJ32.EXE
3. Rar.exe
......@@ -183,13 +192,13 @@ the appropriate archivers as described in the previous section.
Step 2: Edit the configuration files
------------------------------------
At a minimum, you will need to edit DDArcViewerFileTypes.cfg to make sure
At a minimum, you will need to edit dd_arc_viewer_file_types.cfg to make sure
that the archive command lines are correct for your system and that the text
view commands are correct. If you're running your BBS in Linux, you will
first need to comment the Windows command lines and uncomment the Linux
command lines. See section 6: Archive file type configuration file.
If desired, you can also edit DDArcViewer.cfg to change script options
If desired, you can also edit dd_arc_viewer.cfg to change script options
such as the interface type (lightbar/traditional) and colors. See section
5: Main configuration file.
......@@ -207,18 +216,18 @@ INS, the line below (or above) will be copied and inserted as a new line.
When editing a viewable file type, you will need to enter the file extension
and the command line used to view it. The file extension is fairly
self-explanatory. For the command line, use the following (this assumes
DDArcViewer.js was copied to your sbbs\exec diretory):
?DDArcViewer.js %s
If you copied DDArcViewer.js and its other files to another directory, you
will need to provide the path to DDArcViewer.js (i.e.,
?/sbbs/ArcViewer/DDArcViewer.js %s). As an example, your Viewable File Type
dd_arc_viewer.js was copied to your sbbs\exec diretory):
?dd_arc_viewer.js %s
If you copied dd_arc_viewer.js and its other files to another directory, you
will need to provide the path to dd_arc_viewer.js (i.e.,
?/sbbs/ArcViewer/dd_arc_viewer.js %s). As an example, your Viewable File Type
window should look similar to the following:
+[¦][?]--------------------------------------+
¦ Viewable File Type ¦
¦--------------------------------------------¦
¦ ¦File Extension ZIP ¦
¦ ¦Command Line ?DDArcViewer.js %f ¦
¦ ¦Access Requirements ¦
+[|][?]--------------------------------------+
| Viewable File Type |
|--------------------------------------------|
| |File Extension ZIP |
| |Command Line ?dd_arc_viewer.js %f |
| |Access Requirements |
+--------------------------------------------+
......@@ -233,7 +242,7 @@ interfere with the next user's use of the archive viewer.
If you are not already using a logout script, follow these steps:
1. Create a file in your sbbs\exec directory called logout.js
2. Add this line to it (assuming that the archive viewer scripts are in sbbs\exec):
load("DDArcViewerCleanup.js");
load("dd_arc_viewer_cleanup.js");
3. Add your logout script to Synchronet's configuration:
A. Run Synchronet's configuration program (SCFG)
B. From the main menu, choose "System".
......@@ -245,7 +254,7 @@ load("DDArcViewerCleanup.js");
If you already have a logout script (using JavaScript), you just need to add the
following line to it:
load("DDArcViewerCleanup.js");
load("dd_arc_viewer_cleanup.js");
Step 5: If you use a JavaScript command shell, update it
......@@ -264,7 +273,7 @@ from triggering actions in your command shell.
5. Main configuration file
==========================
If you want to change the default beavior and colors, you can edit the
DDArcViewer.cfg file, which is a plain text file. The configuration file
dd_arc_viewer.cfg file, which is a plain text file. The configuration file
has two sections: A behavior section (denoted by [BEHAVIOR]) and a colors
section (denoted by [COLORS]). For each setting or color, the syntax is as
folows:
......@@ -347,7 +356,7 @@ highlightedFile Selected files in lightbar mode
6. Archive file type configuration file
=======================================
The configuration file DDArcViewerFileTypes.cfg defines the files that
The configuration file dd_arc_viewer_file_types.cfg defines the files that
you want to be viewable by the archive viewer. Viewable file types are
specified by their extension in square brackets. Each archive file type
must have a view command and an extract command. Text files must have only
......
......@@ -2,6 +2,10 @@ Revision History for Digital Distortion Archive Viewer
======================================================
Version Date Description
------- ---- -----------
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
archive types can still be configured.
1.03 2009-12-20 Updated DDArcViewer.js to be able to handle command-line
parameters with spaces in them as single parameters,
thanks to a function posted by Tracker1 of The Roughnecks
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment