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 _ = require('lodash');
const pty = require('node-pty');
const paths = require('path');
let archiveUtil;
@ -75,32 +76,56 @@ module.exports = class ArchiveUtil {
}
if(_.isObject(Config.fileTypes)) {
Object.keys(Config.fileTypes).forEach(mimeType => {
const fileType = Config.fileTypes[mimeType];
if(fileType.sig) {
fileType.sig = Buffer.from(fileType.sig, 'hex');
fileType.offset = fileType.offset || 0;
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 = fileType.offset + fileType.sig.length;
const sigLen = ft.offset + ft.sig.length;
if(sigLen > this.longestSignature) {
this.longestSignature = sigLen;
}
};
Object.keys(Config.fileTypes).forEach(mimeType => {
const fileType = Config.fileTypes[mimeType];
if(Array.isArray(fileType)) {
fileType.forEach(ft => {
if(ft.sig) {
updateSig(ft);
}
});
} else if(fileType.sig) {
updateSig(fileType);
}
});
}
}
getArchiver(mimeTypeOrExtension) {
mimeTypeOrExtension = resolveMimeType(mimeTypeOrExtension);
getArchiver(mimeTypeOrExtension, justExtention) {
const mimeType = resolveMimeType(mimeTypeOrExtension);
if(!mimeTypeOrExtension) { // lookup returns false on failure
if(!mimeType) { // lookup returns false on failure
return;
}
const archiveHandler = _.get( Config, [ 'fileTypes', mimeTypeOrExtension, 'archiveHandler'] );
if(archiveHandler) {
return _.get( Config, [ 'archives', 'archivers', archiveHandler ] );
let fileType = _.get(Config, [ 'fileTypes', mimeType ] );
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 => {
if(!fileTypeInfo.sig) {
const fileTypeInfos = Array.isArray(fileTypeInfo) ? fileTypeInfo : [ fileTypeInfo ];
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) {
return false;
}
const comp = buf.slice(fileTypeInfo.offset, fileTypeInfo.offset + fileTypeInfo.sig.length);
return (fileTypeInfo.sig.equals(comp));
const comp = buf.slice(fti.offset, fti.offset + fti.sig.length);
return (fti.sig.equals(comp));
});
});
return cb(archFormat ? null : Errors.General('Unknown type'), archFormat);
@ -162,7 +190,7 @@ module.exports = class ArchiveUtil {
}
compressTo(archType, archivePath, files, cb) {
const archiver = this.getArchiver(archType);
const archiver = this.getArchiver(archType, paths.extname(archivePath));
if(!archiver) {
return cb(Errors.Invalid(`Unknown archive type: ${archType}`));
@ -196,7 +224,7 @@ module.exports = class ArchiveUtil {
haveFileList = true;
}
const archiver = this.getArchiver(archType);
const archiver = this.getArchiver(archType, paths.extname(archivePath));
if(!archiver) {
return cb(Errors.Invalid(`Unknown archive type: ${archType}`));
@ -236,7 +264,7 @@ module.exports = class ArchiveUtil {
}
listEntries(archivePath, archType, cb) {
const archiver = this.getArchiver(archType);
const archiver = this.getArchiver(archType, paths.extname(archivePath));
if(!archiver) {
return cb(Errors.Invalid(`Unknown archive type: ${archType}`));

View File

@ -297,6 +297,16 @@ function getDefaultConfig() {
'--filemodifydate', '--fileaccessdate', '--fileinodechangedate', '--createdate', '--modifydate',
'--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',
offset : 0,
archiveHandler : '7Zip',
}
},
// :TODO: update archives::formats to fall here
// * archive handler -> archiveHandler (consider archive if archiveHandler present)
// * sig, offset, ...
// * mime-db -> exts lookup
// *
//
// Generics that need further mapping
//
'application/octet-stream' : [
{
desc : 'Amiga DISKMASHER',
sig : '444d5321', // DMS!
ext : '.dms',
shortDescUtil : 'XDMS2Desc',
longDescUtil : 'XDMS2LongDesc',
}
]
},
archives : {

View File

@ -24,6 +24,7 @@ const controlCodesToAnsi = require('./color_codes.js').controlCodesToAnsi;
const async = require('async');
const _ = require('lodash');
const moment = require('moment');
const paths = require('path');
exports.moduleInfo = {
name : 'File Area List',
@ -252,7 +253,18 @@ exports.getModule = class FileAreaList extends MenuModule {
if(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 {
entryInfo.archiveTypeDesc = 'N/A';
}

View File

@ -487,8 +487,19 @@ function populateFileEntryWithArchive(fileEntry, filePath, stepInfo, iterator, c
);
}
function getInfoExtractUtilForDesc(mimeType, descType) {
let util = _.get(Config, [ 'fileTypes', mimeType, `${descType}DescUtil` ]);
function getInfoExtractUtilForDesc(mimeType, filePath, descType) {
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)) {
return;
}
@ -508,7 +519,7 @@ function populateFileEntryInfoFromFile(fileEntry, filePath, cb) {
}
async.eachSeries( [ 'short', 'long' ], (descType, nextDesc) => {
const util = getInfoExtractUtilForDesc(mimeType, descType);
const util = getInfoExtractUtilForDesc(mimeType, filePath, descType);
if(!util) {
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
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/) |
| 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 |
| 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) |
- exiftool & other external tools
| exiftool | [ExifTool](https://www.sno.phy.queensu.ca/~phil/exiftool/) | libimage-exiftool-perl | perl-Image-ExifTool | Unknown
| xdms | Unpack/view Amiga DMS | [xdms](http://manpages.ubuntu.com/manpages/trusty/man1/xdms.1.html) | xdms | Unknown
## Config Files