Use Config.fileTypes with mime-db backed MIME types; remove old archives.formats{}
This commit is contained in:
parent
f22f03d528
commit
0e5d0c53d2
|
@ -5,6 +5,7 @@
|
||||||
const Config = require('./config.js').config;
|
const Config = require('./config.js').config;
|
||||||
const stringFormat = require('./string_format.js');
|
const stringFormat = require('./string_format.js');
|
||||||
const Errors = require('./enig_error.js').Errors;
|
const Errors = require('./enig_error.js').Errors;
|
||||||
|
const resolveMimeType = require('./mime_util.js').resolveMimeType;
|
||||||
|
|
||||||
// base/modules
|
// base/modules
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
@ -19,9 +20,6 @@ class Archiver {
|
||||||
this.decompress = config.decompress;
|
this.decompress = config.decompress;
|
||||||
this.list = config.list;
|
this.list = config.list;
|
||||||
this.extract = config.extract;
|
this.extract = config.extract;
|
||||||
|
|
||||||
/*this.sig = new Buffer(config.sig, 'hex');
|
|
||||||
this.offset = config.offset || 0;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ok() {
|
ok() {
|
||||||
|
@ -76,39 +74,33 @@ module.exports = class ArchiveUtil {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_.has(Config, 'archives.formats')) {
|
if(_.isObject(Config.fileTypes)) {
|
||||||
Object.keys(Config.archives.formats).forEach(fmtKey => {
|
Object.keys(Config.fileTypes).forEach(mimeType => {
|
||||||
|
const fileType = Config.fileTypes[mimeType];
|
||||||
|
if(fileType.sig) {
|
||||||
|
fileType.sig = new Buffer(fileType.sig, 'hex');
|
||||||
|
fileType.offset = fileType.offset || 0;
|
||||||
|
|
||||||
Config.archives.formats[fmtKey].sig = new Buffer(Config.archives.formats[fmtKey].sig, 'hex');
|
// :TODO: this is broken: sig is NOT this long, it's sig.length long; offset needs to allow for -negative values as well
|
||||||
Config.archives.formats[fmtKey].offset = Config.archives.formats[fmtKey].offset || 0;
|
const sigLen =fileType.offset + fileType.sig.length;
|
||||||
|
|
||||||
const sigLen = Config.archives.formats[fmtKey].offset + Config.archives.formats[fmtKey].sig.length;
|
|
||||||
if(sigLen > this.longestSignature) {
|
if(sigLen > this.longestSignature) {
|
||||||
this.longestSignature = sigLen;
|
this.longestSignature = sigLen;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
getArchiver(mimeTypeOrExtension) {
|
||||||
getArchiver(archType) {
|
mimeTypeOrExtension = resolveMimeType(mimeTypeOrExtension);
|
||||||
if(!archType || 0 === archType.length) {
|
|
||||||
|
if(!mimeTypeOrExtension) { // lookup returns false on failure
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
archType = archType.toLowerCase();
|
const archiveHandler = _.get( Config, [ 'fileTypes', mimeTypeOrExtension, 'archiveHandler'] );
|
||||||
return this.archivers[archType];
|
if(archiveHandler) {
|
||||||
}*/
|
return _.get( Config, [ 'archives', 'archivers', archiveHandler ] );
|
||||||
|
|
||||||
getArchiver(archType) {
|
|
||||||
if(!archType || 0 === archType.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_.has(Config, [ 'archives', 'formats', archType, 'handler' ] ) &&
|
|
||||||
_.has(Config, [ 'archives', 'archivers', Config.archives.formats[archType].handler ] ))
|
|
||||||
{
|
|
||||||
return Config.archives.archivers[ Config.archives.formats[archType].handler ];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,10 +113,6 @@ module.exports = class ArchiveUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
detectType(path, cb) {
|
detectType(path, cb) {
|
||||||
if(!_.has(Config, 'archives.formats')) {
|
|
||||||
return cb(Errors.DoesNotExist('No formats configured'));
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.open(path, 'r', (err, fd) => {
|
fs.open(path, 'r', (err, fd) => {
|
||||||
if(err) {
|
if(err) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
|
@ -136,15 +124,19 @@ module.exports = class ArchiveUtil {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
const archFormat = _.findKey(Config.archives.formats, archFormat => {
|
const archFormat = _.findKey(Config.fileTypes, fileTypeInfo => {
|
||||||
const lenNeeded = archFormat.offset + archFormat.sig.length;
|
if(!fileTypeInfo.sig) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lenNeeded = fileTypeInfo.offset + fileTypeInfo.sig.length;
|
||||||
|
|
||||||
if(bytesRead < lenNeeded) {
|
if(bytesRead < lenNeeded) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const comp = buf.slice(archFormat.offset, archFormat.offset + archFormat.sig.length);
|
const comp = buf.slice(fileTypeInfo.offset, fileTypeInfo.offset + fileTypeInfo.sig.length);
|
||||||
return (archFormat.sig.equals(comp));
|
return (fileTypeInfo.sig.equals(comp));
|
||||||
});
|
});
|
||||||
|
|
||||||
return cb(archFormat ? null : Errors.General('Unknown type'), archFormat);
|
return cb(archFormat ? null : Errors.General('Unknown type'), archFormat);
|
||||||
|
@ -157,19 +149,13 @@ module.exports = class ArchiveUtil {
|
||||||
// so we have this horrible, horrible hack:
|
// so we have this horrible, horrible hack:
|
||||||
let err;
|
let err;
|
||||||
proc.once('data', d => {
|
proc.once('data', d => {
|
||||||
if(_.isString(d) && d.startsWith('execvp(3) failed.: No such file or directory')) {
|
if(_.isString(d) && d.startsWith('execvp(3) failed.')) {
|
||||||
err = new Error(`${action} failed: ${d.trim()}`);
|
err = Errors.ExternalProcess(`${action} failed: ${d.trim()}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
proc.once('exit', exitCode => {
|
proc.once('exit', exitCode => {
|
||||||
if(exitCode) {
|
return cb(exitCode ? Errors.ExternalProcess(`${action} failed with exit code: ${exitCode}`) : err);
|
||||||
return cb(new Error(`${action} failed with exit code: ${exitCode}`));
|
|
||||||
}
|
|
||||||
if(err) {
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
return cb(null);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +163,7 @@ module.exports = class ArchiveUtil {
|
||||||
const archiver = this.getArchiver(archType);
|
const archiver = this.getArchiver(archType);
|
||||||
|
|
||||||
if(!archiver) {
|
if(!archiver) {
|
||||||
return cb(new Error(`Unknown archive type: ${archType}`));
|
return cb(Errors.Invalid(`Unknown archive type: ${archType}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const fmtObj = {
|
const fmtObj = {
|
||||||
|
@ -205,7 +191,7 @@ module.exports = class ArchiveUtil {
|
||||||
const archiver = this.getArchiver(archType);
|
const archiver = this.getArchiver(archType);
|
||||||
|
|
||||||
if(!archiver) {
|
if(!archiver) {
|
||||||
return cb(new Error(`Unknown archive type: ${archType}`));
|
return cb(Errors.Invalid(`Unknown archive type: ${archType}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const fmtObj = {
|
const fmtObj = {
|
||||||
|
@ -235,7 +221,7 @@ module.exports = class ArchiveUtil {
|
||||||
const archiver = this.getArchiver(archType);
|
const archiver = this.getArchiver(archType);
|
||||||
|
|
||||||
if(!archiver) {
|
if(!archiver) {
|
||||||
return cb(new Error(`Unknown archive type: ${archType}`));
|
return cb(Errors.Invalid(`Unknown archive type: ${archType}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const fmtObj = {
|
const fmtObj = {
|
||||||
|
@ -254,7 +240,7 @@ module.exports = class ArchiveUtil {
|
||||||
|
|
||||||
proc.once('exit', exitCode => {
|
proc.once('exit', exitCode => {
|
||||||
if(exitCode) {
|
if(exitCode) {
|
||||||
return cb(new Error(`List failed with exit code: ${exitCode}`));
|
return cb(Errors.ExternalProcess(`List failed with exit code: ${exitCode}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const entryGroupOrder = archiver.list.entryGroupOrder || { byteSize : 1, fileName : 2 };
|
const entryGroupOrder = archiver.list.entryGroupOrder || { byteSize : 1, fileName : 2 };
|
||||||
|
|
133
core/config.js
133
core/config.js
|
@ -264,6 +264,83 @@ function getDefaultConfig() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fileTypes : {
|
||||||
|
//
|
||||||
|
// File types explicitly known to the system. Here we can configure
|
||||||
|
// information extraction, archive treatment, etc.
|
||||||
|
//
|
||||||
|
// MIME types can be found in mime-db: https://github.com/jshttp/mime-db
|
||||||
|
//
|
||||||
|
// Resources for signature/magic bytes:
|
||||||
|
// * http://www.garykessler.net/library/file_sigs.html
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// :TODO: text/x-ansi -> SAUCE extraction for .ans uploads
|
||||||
|
|
||||||
|
//
|
||||||
|
// Audio
|
||||||
|
//
|
||||||
|
'audio/mpeg' : {
|
||||||
|
desc : 'MP3 Audio',
|
||||||
|
infoExtract : {
|
||||||
|
cmd : `${__dirname}./../util/exif2desc.js`, // ensure chmod +x
|
||||||
|
args : [ '{filePath}' ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
//
|
||||||
|
// Archives
|
||||||
|
//
|
||||||
|
'application/zip' : {
|
||||||
|
desc : 'ZIP Archive',
|
||||||
|
sig : '504b0304',
|
||||||
|
offset : 0,
|
||||||
|
archiveHandler : '7Zip',
|
||||||
|
},
|
||||||
|
'application/x-arj' : {
|
||||||
|
desc : 'ARJ Archive',
|
||||||
|
sig : '60ea',
|
||||||
|
offset : 0,
|
||||||
|
archiveHandler : 'Arj',
|
||||||
|
},
|
||||||
|
'application/x-rar-compressed' : {
|
||||||
|
desc : 'RAR Archive',
|
||||||
|
sig : '526172211a0700',
|
||||||
|
offset : 0,
|
||||||
|
archiveHandler : 'Rar',
|
||||||
|
},
|
||||||
|
'application/gzip' : {
|
||||||
|
desc : 'Gzip Archive',
|
||||||
|
sig : '1f8b',
|
||||||
|
offset : 0,
|
||||||
|
archiveHandler : '7Zip',
|
||||||
|
},
|
||||||
|
// :TODO: application/x-bzip
|
||||||
|
'application/x-bzip2' : {
|
||||||
|
desc : 'BZip2 Archive',
|
||||||
|
sig : '425a68',
|
||||||
|
offset : 0,
|
||||||
|
archiveHandler : '7Zip',
|
||||||
|
},
|
||||||
|
'application/x-lzh-compressed' : {
|
||||||
|
desc : 'LHArc Archive',
|
||||||
|
sig : '2d6c68',
|
||||||
|
offset : 2,
|
||||||
|
archiveHandler : 'Lha',
|
||||||
|
},
|
||||||
|
'application/x-7z-compressed' : {
|
||||||
|
desc : '7-Zip Archive',
|
||||||
|
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
|
||||||
|
// *
|
||||||
|
},
|
||||||
|
|
||||||
archives : {
|
archives : {
|
||||||
archivers : {
|
archivers : {
|
||||||
'7Zip' : {
|
'7Zip' : {
|
||||||
|
@ -348,62 +425,6 @@ function getDefaultConfig() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
formats : {
|
|
||||||
//
|
|
||||||
// Resources
|
|
||||||
// * http://www.garykessler.net/library/file_sigs.html
|
|
||||||
//
|
|
||||||
zip : {
|
|
||||||
sig : '504b0304',
|
|
||||||
offset : 0,
|
|
||||||
exts : [ 'zip' ],
|
|
||||||
handler : '7Zip',
|
|
||||||
desc : 'ZIP Archive',
|
|
||||||
},
|
|
||||||
'7z' : {
|
|
||||||
sig : '377abcaf271c',
|
|
||||||
offset : 0,
|
|
||||||
exts : [ '7z' ],
|
|
||||||
handler : '7Zip',
|
|
||||||
desc : '7-Zip Archive',
|
|
||||||
},
|
|
||||||
arj : {
|
|
||||||
sig : '60ea',
|
|
||||||
offset : 0,
|
|
||||||
exts : [ 'arj' ],
|
|
||||||
handler : 'Arj',
|
|
||||||
desc : 'ARJ Archive',
|
|
||||||
},
|
|
||||||
rar : {
|
|
||||||
sig : '526172211a0700',
|
|
||||||
offset : 0,
|
|
||||||
exts : [ 'rar' ],
|
|
||||||
handler : 'Rar',
|
|
||||||
desc : 'RAR Archive',
|
|
||||||
},
|
|
||||||
gzip : {
|
|
||||||
sig : '1f8b',
|
|
||||||
offset : 0,
|
|
||||||
exts : [ 'gz' ],
|
|
||||||
handler : '7Zip',
|
|
||||||
desc : 'Gzip Archive',
|
|
||||||
},
|
|
||||||
bzip : {
|
|
||||||
sig : '425a68',
|
|
||||||
offset : 0,
|
|
||||||
exts : [ 'bz2' ],
|
|
||||||
handler : '7Zip',
|
|
||||||
desc : 'BZip2 Archive',
|
|
||||||
},
|
|
||||||
lzh : {
|
|
||||||
sig : '2d6c68',
|
|
||||||
offset : 2,
|
|
||||||
exts : [ 'lzh', 'ice' ],
|
|
||||||
handler : 'Lha',
|
|
||||||
desc : 'LHArc Archive',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
fileTransferProtocols : {
|
fileTransferProtocols : {
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* jslint node: true */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const mimeTypes = require('mime-types');
|
||||||
|
|
||||||
|
exports.resolveMimeType = resolveMimeType;
|
||||||
|
|
||||||
|
function resolveMimeType(query) {
|
||||||
|
return mimeTypes.extension(query) || mimeTypes.lookup(query) || undefined; // lookup() returns false; we want undefined
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ const Config = require('../core/config.js').config;
|
||||||
const DownloadQueue = require('../core/download_queue.js');
|
const DownloadQueue = require('../core/download_queue.js');
|
||||||
const FileAreaWeb = require('../core/file_area_web.js');
|
const FileAreaWeb = require('../core/file_area_web.js');
|
||||||
const FileBaseFilters = require('../core/file_base_filter.js');
|
const FileBaseFilters = require('../core/file_base_filter.js');
|
||||||
|
const resolveMimeType = require('../core/mime_util.js').resolveMimeType;
|
||||||
|
|
||||||
const cleanControlCodes = require('../core/string_util.js').cleanControlCodes;
|
const cleanControlCodes = require('../core/string_util.js').cleanControlCodes;
|
||||||
|
|
||||||
|
@ -236,9 +237,8 @@ exports.getModule = class FileAreaList extends MenuModule {
|
||||||
});
|
});
|
||||||
|
|
||||||
if(entryInfo.archiveType) {
|
if(entryInfo.archiveType) {
|
||||||
entryInfo.archiveTypeDesc = _.has(Config, [ 'archives', 'formats', entryInfo.archiveType, 'desc' ]) ?
|
const mimeType = resolveMimeType(entryInfo.archiveType);
|
||||||
Config.archives.formats[entryInfo.archiveType].desc :
|
entryInfo.archiveTypeDesc = mimeType ? _.get(Config, [ 'fileTypes', mimeType, 'desc' ] ) || mimeType : entryInfo.archiveType;
|
||||||
entryInfo.archiveType;
|
|
||||||
} else {
|
} else {
|
||||||
entryInfo.archiveTypeDesc = 'N/A';
|
entryInfo.archiveTypeDesc = 'N/A';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue