* Added ability to serve static files from web server
* Web server can have custom error pages, e.g. 404.html * "file_area" stuff -> "file_base" * Fix some rare bugs in theme/art loading * Adjust tab order dynamically for file upload details
This commit is contained in:
10
core/art.js
10
core/art.js
@@ -78,7 +78,7 @@ function getArtFromPath(path, options, cb) {
|
||||
return iconv.decode(data, encoding);
|
||||
} else {
|
||||
const eofMarker = defaultEofFromExtension(ext);
|
||||
return iconv.decode(sliceAtEOF(data, eofMarker), encoding);
|
||||
return iconv.decode(eofMarker ? sliceAtEOF(data, eofMarker) : data, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,11 +213,15 @@ function getArt(name, options, cb) {
|
||||
}
|
||||
|
||||
function defaultEncodingFromExtension(ext) {
|
||||
return SUPPORTED_ART_TYPES[ext.toLowerCase()].defaultEncoding;
|
||||
const artType = SUPPORTED_ART_TYPES[ext.toLowerCase()];
|
||||
return artType ? artType.defaultEncoding : 'utf8';
|
||||
}
|
||||
|
||||
function defaultEofFromExtension(ext) {
|
||||
return SUPPORTED_ART_TYPES[ext.toLowerCase()].eof;
|
||||
const artType = SUPPORTED_ART_TYPES[ext.toLowerCase()];
|
||||
if(artType) {
|
||||
return artType.eof;
|
||||
}
|
||||
}
|
||||
|
||||
// :TODO: Implement the following
|
||||
|
||||
@@ -223,6 +223,8 @@ function getDefaultConfig() {
|
||||
contentServers : {
|
||||
web : {
|
||||
domain : 'another-fine-enigma-bbs.org',
|
||||
|
||||
staticRoot : paths.join(__dirname, './../www'),
|
||||
|
||||
http : {
|
||||
enabled : false,
|
||||
@@ -364,6 +366,9 @@ function getDefaultConfig() {
|
||||
},
|
||||
|
||||
fileTransferProtocols : {
|
||||
//
|
||||
// See http://www.synchro.net/docs/sexyz.txt for information on SEXYZ
|
||||
//
|
||||
zmodem8kSexyz : {
|
||||
name : 'ZModem 8k (SEXYZ)',
|
||||
type : 'external',
|
||||
|
||||
@@ -41,15 +41,15 @@ class FileAreaWebAccess {
|
||||
return self.load(callback);
|
||||
},
|
||||
function addWebRoute(callback) {
|
||||
const webServer = getServer(WEB_SERVER_PACKAGE_NAME);
|
||||
if(!webServer) {
|
||||
self.webServer = getServer(WEB_SERVER_PACKAGE_NAME);
|
||||
if(!self.webServer) {
|
||||
return callback(Errors.DoesNotExist(`Server with package name "${WEB_SERVER_PACKAGE_NAME}" does not exist`));
|
||||
}
|
||||
|
||||
const routeAdded = webServer.instance.addRoute({
|
||||
const routeAdded = self.webServer.instance.addRoute({
|
||||
method : 'GET',
|
||||
path : '/f/[a-zA-Z0-9]+$', // :TODO: allow this to be configurable
|
||||
handler : self.routeWebRequest.bind(self),
|
||||
handler : self.routeWebRequestForFile.bind(self),
|
||||
});
|
||||
|
||||
return callback(routeAdded ? null : Errors.General('Failed adding route'));
|
||||
@@ -217,13 +217,10 @@ class FileAreaWebAccess {
|
||||
}
|
||||
|
||||
fileNotFound(resp) {
|
||||
resp.writeHead(404, { 'Content-Type' : 'text/html' } );
|
||||
|
||||
// :TODO: allow custom 404 - mods/<theme>/file_area_web-404.html
|
||||
return resp.end('<html><body>Not found</html>');
|
||||
this.webServer.instance.respondWithError(resp, 404, 'File not found.', 'File Not Found');
|
||||
}
|
||||
|
||||
routeWebRequest(req, resp) {
|
||||
routeWebRequestForFile(req, resp) {
|
||||
const hashId = paths.basename(req.url);
|
||||
|
||||
this.loadServedHashId(hashId, (err, servedItem) => {
|
||||
@@ -259,7 +256,7 @@ class FileAreaWebAccess {
|
||||
});
|
||||
|
||||
const headers = {
|
||||
'Content-Type' : mimeTypes.contentType(paths.extname(filePath)) || mimeTypes.contentType('.bin'),
|
||||
'Content-Type' : mimeTypes.contentType(filePath) || mimeTypes.contentType('.bin'),
|
||||
'Content-Length' : stats.size,
|
||||
'Content-Disposition' : `attachment; filename="${fileEntry.fileName}"`,
|
||||
};
|
||||
|
||||
@@ -25,11 +25,19 @@ const SYSTEM_EOL = require('os').EOL;
|
||||
const TEMP_SUFFIX = 'enigtf-'; // temp CWD/etc.
|
||||
|
||||
/*
|
||||
Notes
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
See core/config.js for external protocol configuration
|
||||
|
||||
|
||||
Resources
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
ZModem
|
||||
* http://gallium.inria.fr/~doligez/zmodem/zmodem.txt
|
||||
* https://github.com/protomouse/synchronet/blob/master/src/sbbs3/zmodem.c
|
||||
|
||||
*/
|
||||
|
||||
exports.moduleInfo = {
|
||||
@@ -6,7 +6,6 @@ const logger = require('./logger.js');
|
||||
|
||||
// deps
|
||||
const async = require('async');
|
||||
const _ = require('lodash');
|
||||
|
||||
const listeningServers = {}; // packageName -> info
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ const http = require('http');
|
||||
const https = require('https');
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs');
|
||||
const paths = require('path');
|
||||
const mimeTypes = require('mime-types');
|
||||
|
||||
const ModuleInfo = exports.moduleInfo = {
|
||||
name : 'Web',
|
||||
@@ -55,6 +57,14 @@ exports.getModule = class WebServerModule extends ServerModule {
|
||||
this.enableHttps = Config.contentServers.web.https.enabled || false;
|
||||
|
||||
this.routes = {};
|
||||
|
||||
if(Config.contentServers.web.staticRoot) {
|
||||
this.addRoute({
|
||||
method : 'GET',
|
||||
path : '/static/.*$',
|
||||
handler : this.routeStaticFile,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
createServer() {
|
||||
@@ -116,8 +126,54 @@ exports.getModule = class WebServerModule extends ServerModule {
|
||||
return route ? route.handler(req, resp) : this.accessDenied(resp);
|
||||
}
|
||||
|
||||
accessDenied(resp) {
|
||||
resp.writeHead(401, { 'Content-Type' : 'text/html' } );
|
||||
return resp.end('<html><body>Access denied</body></html>');
|
||||
respondWithError(resp, code, bodyText, title) {
|
||||
const customErrorPage = paths.join(Config.contentServers.web.staticRoot, `${code}.html`);
|
||||
|
||||
fs.readFile(customErrorPage, 'utf8', (err, data) => {
|
||||
resp.writeHead(code, { 'Content-Type' : 'text/html' } );
|
||||
|
||||
if(err) {
|
||||
return resp.end(`<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>${title}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<article>
|
||||
<h2>${bodyText}</h2>
|
||||
</article>
|
||||
</body>
|
||||
</html>`
|
||||
);
|
||||
}
|
||||
|
||||
return resp.end(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
accessDenied(resp) {
|
||||
return this.respondWithError(resp, 401, 'Access denied.', 'Access Denied');
|
||||
}
|
||||
|
||||
routeStaticFile(req, resp) {
|
||||
const fileName = req.url.substr(req.url.indexOf('/', 1));
|
||||
const filePath = paths.join(Config.contentServers.web.staticRoot, fileName);
|
||||
|
||||
fs.stat(filePath, (err, stats) => {
|
||||
if(err) {
|
||||
return this.respondWithError(resp, 404, 'File not found.', 'File Not Found');
|
||||
}
|
||||
|
||||
const headers = {
|
||||
'Content-Type' : mimeTypes.contentType(filePath) || mimeTypes.contentType('.bin'),
|
||||
'Content-Length' : stats.size,
|
||||
};
|
||||
|
||||
const readStream = fs.createReadStream(filePath);
|
||||
resp.writeHead(200, headers);
|
||||
return readStream.pipe(resp);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -354,16 +354,16 @@ function setClientTheme(client, themeId) {
|
||||
function getThemeArt(options, cb) {
|
||||
//
|
||||
// options - required:
|
||||
// name
|
||||
// client
|
||||
// name
|
||||
//
|
||||
// options - optional
|
||||
// themeId
|
||||
// asAnsi
|
||||
// readSauce
|
||||
// random
|
||||
// client - needed for user's theme/etc.
|
||||
// themeId
|
||||
// asAnsi
|
||||
// readSauce
|
||||
// random
|
||||
//
|
||||
if(!options.themeId && _.has(options.client, 'user.properties.theme_id')) {
|
||||
if(!options.themeId && _.has(options, 'client.user.properties.theme_id')) {
|
||||
options.themeId = options.client.user.properties.theme_id;
|
||||
} else {
|
||||
options.themeId = Config.defaults.theme;
|
||||
@@ -437,9 +437,13 @@ function getThemeArt(options, cb) {
|
||||
],
|
||||
function complete(err, artInfo) {
|
||||
if(err) {
|
||||
options.client.log.debug( { error : err }, 'Cannot find art');
|
||||
if(options.client) {
|
||||
options.client.log.debug( { error : err.message }, 'Cannot find theme art' );
|
||||
} else {
|
||||
Log.debug( { error : err.message }, 'Cannot find theme art' );
|
||||
}
|
||||
}
|
||||
cb(err, artInfo);
|
||||
return cb(err, artInfo);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user