diff --git a/xtrn/dd_upload_processor/ddup.js b/xtrn/dd_upload_processor/ddup.js index 72b0c16a011b59c7c0b8ae2cd887d02d658ad799..de7386451b39c0da442d9e2311ff38a32ce1fe47 100644 --- a/xtrn/dd_upload_processor/ddup.js +++ b/xtrn/dd_upload_processor/ddup.js @@ -9,18 +9,16 @@ * BBS: Digital Distortion * BBS address: digdist.bbsindex.com * - * Date Author Description + * Date Author Version Description * 2009-12-25- - * 2009-12-28 Eric Oulashin Initial development - * 2009-12-29 Eric Oulashin Version 1.00 - * Initial public release - * 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 too after extracting - * an archive so that they're all readable. - * 2022-06-11 Eric Oulashin Version 1.03 - * Removed the chmod stuff, as it is actually not needed. + * 2009-12-28 Eric Oulashin Initial development + * 2009-12-29 Eric Oulashin 1.00 Initial public release + * 2022-06-08 Eric Oulashin 1.01 Made fixes to get the scanner functionality working properly in Linux + * 2022-06-11 Eric Oulashin 1.02 Improved file/dir permissions more: Set file permissions after extracting + * 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. + * 2023-08-06 Eric Oulashin 1.04 Now uses Synchronet's built-in archiver (added in Synchronet 3.19), + * if available, to extract archives. */ /* Command-line arguments: @@ -48,8 +46,8 @@ gStartupPath = backslash(gStartupPath.replace(/[\/\\][^\/\\]*$/,'')); load(gStartupPath + "ddup_cleanup.js"); // Version information -var gDDUPVersion = "1.03"; -var gDDUPVerDate = "2022-06-11"; +var gDDUPVersion = "1.04"; +var gDDUPVerDate = "2023-08-06"; // Store whether or not this is running in Windows var gRunningInWindows = /^WIN/.test(system.platform.toUpperCase()); @@ -822,78 +820,104 @@ function fixPathSlashes(pPath) // Return value: A blank string on success, or an error message on failure. function extractFileToDir(pFilename, pWorkDir) { - // If pFilename doesn't exist, then return with an error. - if (typeof(pFilename) != "string") - return ("Invalid filename specified."); - if (pFilename.length == 0) - return ("No filename specified."); - if (!file_exists(pFilename)) - return ("The specified file does not exist."); - - // If pWorkDir is blank, then return with an error. - if (typeof(pWorkDir) != "string") - return ("Unknown argument specified for the work directory."); - if (pWorkDir.length == 0) - return ("No work directory specified."); - - // If pWorkDir ends with a slash, remove it. - if ((/\/$/.test(pWorkDir)) || (/\\$/.test(pWorkDir))) - pWorkDir = pWorkDir.substr(0, pWorkDir.length-1); - - // If the work directory doesn't exist, then return with - // an error. - // Note: file_exists() doesn't seem to work properly with directories. - //if (!file_exists(pWorkDir)) - // return ("The work directory doesn't exist."); - - var filenameExt = getFilenameExtension(pFilename); - // Return with errors if there are problems. - if (filenameExt.length == 0) - return ("Can't extract (no file extension)."); - if (typeof(gFileTypeCfg[filenameExt]) == "undefined") - return ("Can't extract " + getFilenameFromPath(pFilename) + " (I don't know how)."); - if (gFileTypeCfg[filenameExt].extractCmd == "") - return ("Can't extract " + getFilenameFromPath(pFilename) + " (I don't know how)."); - - var retval = ""; - - // Extract the file to the work directory. - var extractCmd = gFileTypeCfg[filenameExt].extractCmd.replace("%FILENAME%", "\"" + fixPathSlashes(pFilename) + "\""); - extractCmd = extractCmd.replace("%FILESPEC% ", ""); - extractCmd = extractCmd.replace("%TO_DIR%", "\"" + fixPathSlashes(pWorkDir) + "\""); - var retCode = system.exec(extractCmd); - if (retCode != 0) - return ("Extract failed with exit code " + retCode); - // For each file in the work directory: - // If the file has an extract command - // Extract it to a subdir in the temp dir - // Delete the archive - var files = directory(pWorkDir + "/*"); - for (var i in files) - { - // If the file has an extract command, then extract it to a - // temp directory in the work directory. - filenameExt = getFilenameExtension(files[i]); - if ((typeof(gFileTypeCfg[filenameExt]) != "undefined") && - ((gFileTypeCfg[filenameExt].extractCmd != ""))) - { - // Create the temp directory and extract the file there. - var workDir = pWorkDir + "/" + getFilenameFromPath(files[i] + "_temp"); - if (mkdir(workDir)) - retval = extractFileToDir(files[i], workDir); - else - retval = "Unable to create a temporary directory."; - - // If there was no problem, then delete the archive file. Otherwise, - // stop going through the list of files. - if (retval.length == 0) - file_remove(files[i]); - else - break; - } - } + // If pFilename doesn't exist, then return with an error. + if (typeof(pFilename) != "string") + return ("Invalid filename specified."); + if (pFilename.length == 0) + return ("No filename specified."); + if (!file_exists(pFilename)) + return ("The specified file does not exist."); + + // If pWorkDir is blank, then return with an error. + if (typeof(pWorkDir) != "string") + return ("Unknown argument specified for the work directory."); + if (pWorkDir.length == 0) + return ("No work directory specified."); + + // If pWorkDir ends with a slash, remove it. + if ((/\/$/.test(pWorkDir)) || (/\\$/.test(pWorkDir))) + pWorkDir = pWorkDir.substr(0, pWorkDir.length-1); + + // If the work directory doesn't exist, then return with + // an error. + // Note: file_exists() doesn't seem to work properly with directories. + //if (!file_exists(pWorkDir)) + // return ("The work directory doesn't exist."); + + var filenameExt = getFilenameExtension(pFilename); + // Return with errors if there are problems. + if (filenameExt.length == 0) + return ("Can't extract (no file extension)."); + if (typeof(gFileTypeCfg[filenameExt]) == "undefined") + return ("Can't extract " + getFilenameFromPath(pFilename) + " (I don't know how)."); + if (gFileTypeCfg[filenameExt].extractCmd == "") + return ("Can't extract " + getFilenameFromPath(pFilename) + " (I don't know how)."); + + var retval = ""; + + // Extract the file to the work directory. + // 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. + var builtInExtractSucceeded = false; + if (typeof(Archive) === "function") + { + var arcFilenameFixed = fixPathSlashes(pFilename); + var arcFile = new Archive(arcFilenameFixed); + 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. + var numFilesExtracted = arcFile.extract(pWorkDir, 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) + { + // Synchronet's internal archiver was unable to extract it. + log(LOG_ERR, "DD Upload Processor: Synchronet internal archiver failed to extract " + arcFilenameFixed + ": " + e); + } + } + if (!builtInExtractSucceeded) + { + var extractCmd = gFileTypeCfg[filenameExt].extractCmd.replace("%FILENAME%", "\"" + fixPathSlashes(pFilename) + "\""); + extractCmd = extractCmd.replace("%FILESPEC% ", ""); + extractCmd = extractCmd.replace("%TO_DIR%", "\"" + fixPathSlashes(pWorkDir) + "\""); + var retCode = system.exec(extractCmd); + if (retCode != 0) + return ("Extract failed with exit code " + retCode); + } + // For each file in the work directory: + // If the file has an extract command + // Extract it to a subdir in the temp dir + // Delete the archive + var files = directory(pWorkDir + "/*"); + for (var i in files) + { + // If the file has an extract command, then extract it to a + // temp directory in the work directory. + filenameExt = getFilenameExtension(files[i]); + if ((typeof(gFileTypeCfg[filenameExt]) != "undefined") && ((gFileTypeCfg[filenameExt].extractCmd != ""))) + { + // Create the temp directory and extract the file there. + var workDir = pWorkDir + "/" + getFilenameFromPath(files[i] + "_temp"); + if (mkdir(workDir)) + retval = extractFileToDir(files[i], workDir); + else + retval = "Unable to create a temporary directory."; - return retval; + // If there was no problem, then delete the archive file. Otherwise, + // stop going through the list of files. + if (retval.length == 0) + file_remove(files[i]); + else + break; + } + } + + return retval; } // This function executes an OS command and returns its output as an diff --git a/xtrn/dd_upload_processor/readme.txt b/xtrn/dd_upload_processor/readme.txt index f5ae1d15d107a91f8a500beb9f8976d87dcaefd9..ff0ef27df0369a0d8feeb15d451c03a12932f13c 100644 --- a/xtrn/dd_upload_processor/readme.txt +++ b/xtrn/dd_upload_processor/readme.txt @@ -1,12 +1,13 @@ Digital Distortion Upload Processor - Version 1.03 - Release date: 2022-06-11 + Version 1.04 + Release date: 2023-08-06 by Eric Oulashin Sysop of Digital Distortion BBS - BBS internet address: digdist.bbsindex.com + BBS internet address: digdist.synchro.net + AKA digitaldistortionbbs.com Email: eric.oulashin@gmail.com @@ -42,9 +43,12 @@ to scan uploaded files, with the added ability to extract compressed files in order to scan the files inside the compressed file. File formats can be specified and configured via a configuration file, -including extraction commands for compressed files. In addition, the -virus scan command can be configured in the main configuration file, -which should allow for the use of any virus scanner, as long as it is a +including extraction commands for compressed files. Synchronet's built-in +archive support (added in Synchronet 3.19) will be used, if available, to +extract archive files. Otherwise, extract commands for archive file types can +be configured in the archive file type configuration file (ddup_file_types.cfg). +In addition, the virus scan command can be configured in the main configuration +file, which should allow for the use of any virus scanner, as long as it is a command-line scanner (no GUI) and is able to take a subdirectory as a command-line parameter. @@ -76,10 +80,18 @@ uploaded file to be rejected. 3. Archive File Software ======================== -Digital Distortion Upload Processor comes with configuration settings to -use various archivers to handle extraction of ZIP, 7Z (7-Zip), RAR, ARJ, MSI, -TAR, GZ, TGZ, and TAR.GZ archives. If you want to use other archiver programs, -you will need to update the configuration to modify the commands used. +Digital Distortion Upload Processor will (try to) use Synchronet's built-in +archive support (if available) to extract archive files. If that fails, it will +fall back on a configured command-line to extract the archive (if configured). +Synchronet's built-in archive support will take precedence over any configured +extraction command (that is, if Synchronet itself is able to extract the +archive, any configured extraction command for that archive file type will not +be uesd). + +Configuration settings to use various archivers to handle extraction of ZIP, 7Z +(7-Zip), RAR, ARJ, MSI, TAR, GZ, TGZ, and TAR.GZ archives. If you want to use +other archiver programs, you will need to update the configuration to modify the +commands used. The file format configuration file included with this script includes extraction command lines (specified by an EXTRACT setting) for various diff --git a/xtrn/dd_upload_processor/version_history.txt b/xtrn/dd_upload_processor/version_history.txt index 25e7d79a1cba0d13c1af80bc2d01cd32c2cd3df3..81cc8dae61a05a22e01c679b4ffb450648d65a35 100644 --- a/xtrn/dd_upload_processor/version_history.txt +++ b/xtrn/dd_upload_processor/version_history.txt @@ -2,6 +2,8 @@ Revision History for Digital Distortion Upload Processor ======================================================== Version Date Description ------- ---- ----------- +1.04 2023-08-06 Now uses Synchronet's built-in archiver (added in + Synchronet 3.19), if available, to extract archives. 1.03 2022-06-11 Removed the chmod updates because they're actually not needed. Some antivirus scanners (such as ClamAV) need a command line parameter to pass the file permissions