Generic MIME types (file types) such as application/octet-stream can how have sub types for handlers (archive, info extract, ...)

+ Add Amiga DMS support via xdms
This commit is contained in:
Bryan Ashby 2018-06-02 16:06:04 -06:00
parent 95422f71ba
commit 3ecadebf91
5 changed files with 108 additions and 40 deletions

View File

@ -11,6 +11,7 @@ const resolveMimeType = require('./mime_util.js').resolveMimeType;
const fs = require('graceful-fs'); const fs = require('graceful-fs');
const _ = require('lodash'); const _ = require('lodash');
const pty = require('node-pty'); const pty = require('node-pty');
const paths = require('path');
let archiveUtil; let archiveUtil;
@ -75,32 +76,56 @@ module.exports = class ArchiveUtil {
} }
if(_.isObject(Config.fileTypes)) { if(_.isObject(Config.fileTypes)) {
const updateSig = (ft) => {
ft.sig = Buffer.from(ft.sig, 'hex');
ft.offset = ft.offset || 0;
// :TODO: this is broken: sig is NOT this long, it's sig.length long; offset needs to allow for -negative values as well
const sigLen = ft.offset + ft.sig.length;
if(sigLen > this.longestSignature) {
this.longestSignature = sigLen;
}
};
Object.keys(Config.fileTypes).forEach(mimeType => { Object.keys(Config.fileTypes).forEach(mimeType => {
const fileType = Config.fileTypes[mimeType]; const fileType = Config.fileTypes[mimeType];
if(fileType.sig) { if(Array.isArray(fileType)) {
fileType.sig = Buffer.from(fileType.sig, 'hex'); fileType.forEach(ft => {
fileType.offset = fileType.offset || 0; if(ft.sig) {
updateSig(ft);
// :TODO: this is broken: sig is NOT this long, it's sig.length long; offset needs to allow for -negative values as well }
const sigLen = fileType.offset + fileType.sig.length; });
if(sigLen > this.longestSignature) { } else if(fileType.sig) {
this.longestSignature = sigLen; updateSig(fileType);
}
} }
}); });
} }
} }
getArchiver(mimeTypeOrExtension) { getArchiver(mimeTypeOrExtension, justExtention) {
mimeTypeOrExtension = resolveMimeType(mimeTypeOrExtension); const mimeType = resolveMimeType(mimeTypeOrExtension);
if(!mimeTypeOrExtension) { // lookup returns false on failure if(!mimeType) { // lookup returns false on failure
return; return;
} }
const archiveHandler = _.get( Config, [ 'fileTypes', mimeTypeOrExtension, 'archiveHandler'] ); let fileType = _.get(Config, [ 'fileTypes', mimeType ] );
if(archiveHandler) {
return _.get( Config, [ 'archives', 'archivers', archiveHandler ] ); if(Array.isArray(fileType)) {
if(!justExtention) {
// need extention for lookup; ambiguous as-is :(
return;
}
// further refine by extention
fileType = fileType.find(ft => justExtention === ft.ext);
}
if(!_.isObject(fileType)) {
return;
}
if(fileType.archiveHandler) {
return _.get( Config, [ 'archives', 'archivers', fileType.archiveHandler ] );
} }
} }
@ -127,18 +152,21 @@ module.exports = class ArchiveUtil {
} }
const archFormat = _.findKey(Config.fileTypes, fileTypeInfo => { const archFormat = _.findKey(Config.fileTypes, fileTypeInfo => {
if(!fileTypeInfo.sig) { const fileTypeInfos = Array.isArray(fileTypeInfo) ? fileTypeInfo : [ fileTypeInfo ];
return false; return fileTypeInfos.find(fti => {
} if(!fti.sig || !fti.archiveHandler) {
return false;
}
const lenNeeded = fileTypeInfo.offset + fileTypeInfo.sig.length; const lenNeeded = fti.offset + fti.sig.length;
if(bytesRead < lenNeeded) { if(bytesRead < lenNeeded) {
return false; return false;
} }
const comp = buf.slice(fileTypeInfo.offset, fileTypeInfo.offset + fileTypeInfo.sig.length); const comp = buf.slice(fti.offset, fti.offset + fti.sig.length);
return (fileTypeInfo.sig.equals(comp)); return (fti.sig.equals(comp));
});
}); });
return cb(archFormat ? null : Errors.General('Unknown type'), archFormat); return cb(archFormat ? null : Errors.General('Unknown type'), archFormat);
@ -162,7 +190,7 @@ module.exports = class ArchiveUtil {
} }
compressTo(archType, archivePath, files, cb) { compressTo(archType, archivePath, files, cb) {
const archiver = this.getArchiver(archType); const archiver = this.getArchiver(archType, paths.extname(archivePath));
if(!archiver) { if(!archiver) {
return cb(Errors.Invalid(`Unknown archive type: ${archType}`)); return cb(Errors.Invalid(`Unknown archive type: ${archType}`));
@ -196,7 +224,7 @@ module.exports = class ArchiveUtil {
haveFileList = true; haveFileList = true;
} }
const archiver = this.getArchiver(archType); const archiver = this.getArchiver(archType, paths.extname(archivePath));
if(!archiver) { if(!archiver) {
return cb(Errors.Invalid(`Unknown archive type: ${archType}`)); return cb(Errors.Invalid(`Unknown archive type: ${archType}`));
@ -236,7 +264,7 @@ module.exports = class ArchiveUtil {
} }
listEntries(archivePath, archType, cb) { listEntries(archivePath, archType, cb) {
const archiver = this.getArchiver(archType); const archiver = this.getArchiver(archType, paths.extname(archivePath));
if(!archiver) { if(!archiver) {
return cb(Errors.Invalid(`Unknown archive type: ${archType}`)); return cb(Errors.Invalid(`Unknown archive type: ${archType}`));

View File

@ -297,6 +297,16 @@ function getDefaultConfig() {
'--filemodifydate', '--fileaccessdate', '--fileinodechangedate', '--createdate', '--modifydate', '--filemodifydate', '--fileaccessdate', '--fileinodechangedate', '--createdate', '--modifydate',
'--metadatadate', '--xmptoolkit' '--metadatadate', '--xmptoolkit'
] ]
},
XDMS2Desc : {
// http://manpages.ubuntu.com/manpages/trusty/man1/xdms.1.html
cmd : 'xdms',
args : [ 'd', '{filePath}' ]
},
XDMS2LongDesc : {
// http://manpages.ubuntu.com/manpages/trusty/man1/xdms.1.html
cmd : 'xdms',
args : [ 'f', '{filePath}' ]
} }
}, },
@ -426,13 +436,20 @@ function getDefaultConfig() {
sig : '377abcaf271c', sig : '377abcaf271c',
offset : 0, offset : 0,
archiveHandler : '7Zip', archiveHandler : '7Zip',
} },
// :TODO: update archives::formats to fall here //
// * archive handler -> archiveHandler (consider archive if archiveHandler present) // Generics that need further mapping
// * sig, offset, ... //
// * mime-db -> exts lookup 'application/octet-stream' : [
// * {
desc : 'Amiga DISKMASHER',
sig : '444d5321', // DMS!
ext : '.dms',
shortDescUtil : 'XDMS2Desc',
longDescUtil : 'XDMS2LongDesc',
}
]
}, },
archives : { archives : {

View File

@ -24,6 +24,7 @@ const controlCodesToAnsi = require('./color_codes.js').controlCodesToAnsi;
const async = require('async'); const async = require('async');
const _ = require('lodash'); const _ = require('lodash');
const moment = require('moment'); const moment = require('moment');
const paths = require('path');
exports.moduleInfo = { exports.moduleInfo = {
name : 'File Area List', name : 'File Area List',
@ -252,7 +253,18 @@ exports.getModule = class FileAreaList extends MenuModule {
if(entryInfo.archiveType) { if(entryInfo.archiveType) {
const mimeType = resolveMimeType(entryInfo.archiveType); const mimeType = resolveMimeType(entryInfo.archiveType);
entryInfo.archiveTypeDesc = mimeType ? _.get(Config, [ 'fileTypes', mimeType, 'desc' ] ) || mimeType : entryInfo.archiveType; let desc;
if(mimeType) {
let fileType = _.get(Config, [ 'fileTypes', mimeType ] );
if(Array.isArray(fileType)) {
// further refine by extention
fileType = fileType.find(ft => paths.extname(currEntry.fileName) === ft.ext);
}
desc = fileType && fileType.desc;
}
entryInfo.archiveTypeDesc = desc || mimeType || entryInfo.archiveType;
//entryInfo.archiveTypeDesc = mimeType ? _.get(Config, [ 'fileTypes', mimeType, 'desc' ] ) || mimeType : entryInfo.archiveType;
} else { } else {
entryInfo.archiveTypeDesc = 'N/A'; entryInfo.archiveTypeDesc = 'N/A';
} }

View File

@ -487,8 +487,19 @@ function populateFileEntryWithArchive(fileEntry, filePath, stepInfo, iterator, c
); );
} }
function getInfoExtractUtilForDesc(mimeType, descType) { function getInfoExtractUtilForDesc(mimeType, filePath, descType) {
let util = _.get(Config, [ 'fileTypes', mimeType, `${descType}DescUtil` ]); let fileType = _.get(Config, [ 'fileTypes', mimeType ] );
if(Array.isArray(fileType)) {
// further refine by extention
fileType = fileType.find(ft => paths.extname(filePath) === ft.ext);
}
if(!_.isObject(fileType)) {
return;
}
let util = _.get(fileType, `${descType}DescUtil`);
if(!_.isString(util)) { if(!_.isString(util)) {
return; return;
} }
@ -508,7 +519,7 @@ function populateFileEntryInfoFromFile(fileEntry, filePath, cb) {
} }
async.eachSeries( [ 'short', 'long' ], (descType, nextDesc) => { async.eachSeries( [ 'short', 'long' ], (descType, nextDesc) => {
const util = getInfoExtractUtilForDesc(mimeType, descType); const util = getInfoExtractUtilForDesc(mimeType, filePath, descType);
if(!util) { if(!util) {
return nextDesc(null); return nextDesc(null);
} }

View File

@ -50,7 +50,7 @@ ENiGMA BBS makes use of a few packages for unarchiving and modem support. They'r
running ENiGMA, but without them you'll miss certain functionality. Once installed, they should be made running ENiGMA, but without them you'll miss certain functionality. Once installed, they should be made
available on your system path. available on your system path.
| Package | Description | Ubuntu Package | CentOS Package Name | Windows Package | | Package | Description | Debian/Ubuntu Package (APT/DEP) | Red Hat Package (YUM/RPM) | Windows Package |
|------------|-----------------------------------|--------------------------------------------|---------------------------------------------------|------------------------------------------------------------------| |------------|-----------------------------------|--------------------------------------------|---------------------------------------------------|------------------------------------------------------------------|
| arj | Unpacking arj archives | `arj` | n/a, binaries [here](http://arj.sourceforge.net/) | [ARJ](http://arj.sourceforge.net/) | | arj | Unpacking arj archives | `arj` | n/a, binaries [here](http://arj.sourceforge.net/) | [ARJ](http://arj.sourceforge.net/) |
| 7zip | Unpacking zip, rar, archives | `p7zip-full` | `p7zip-full` | [7-zip](http://www.7-zip.org/) | | 7zip | Unpacking zip, rar, archives | `p7zip-full` | `p7zip-full` | [7-zip](http://www.7-zip.org/) |
@ -58,8 +58,8 @@ available on your system path.
| Rar | Unpacking rar archives | `unrar` | n/a, binaries [here](https://www.rarlab.com/download.htm) | Unknown | | Rar | Unpacking rar archives | `unrar` | n/a, binaries [here](https://www.rarlab.com/download.htm) | Unknown |
| lrzsz | sz/rz: X/Y/Z modem support | `lrzsz` | `lrzsz` | Unknown | | lrzsz | sz/rz: X/Y/Z modem support | `lrzsz` | `lrzsz` | Unknown |
| sexyz | SexyZ modem support | [sexyz](https://l33t.codes/outgoing/sexyz) | [sexyz](https://l33t.codes/outgoing/sexyz) | Available with [Synchronet](http://wiki.synchro.net/install:win) | | sexyz | SexyZ modem support | [sexyz](https://l33t.codes/outgoing/sexyz) | [sexyz](https://l33t.codes/outgoing/sexyz) | Available with [Synchronet](http://wiki.synchro.net/install:win) |
| exiftool | [ExifTool](https://www.sno.phy.queensu.ca/~phil/exiftool/) | libimage-exiftool-perl | perl-Image-ExifTool | Unknown
- exiftool & other external tools | xdms | Unpack/view Amiga DMS | [xdms](http://manpages.ubuntu.com/manpages/trusty/man1/xdms.1.html) | xdms | Unknown
## Config Files ## Config Files