exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVER, PROJECT_FILE_SERVER, UI_FILE_SERVER, PLUGIN_SERVER, CCXT_SERVER, WEB3_SERVER) { let thisObject = { initialize: initialize, finalize: finalize, run: run } const open = require('open') let port = global.env.HTTP_INTERFACE_PORT let http = require('http') let isHttpServerStarted = false let webhook = new Map() return thisObject function finalize() { } function initialize() { } function run() { startHtttpServer() } function startHtttpServer() { try { if (isHttpServerStarted === false) { gWebServer = http.createServer(onBrowserRequest).listen(port) isHttpServerStarted = true /* Starting the browser now is optional */ if (process.argv.includes("noBrowser")) { //Running Client only with no UI. } else { open('http://localhost:' + port) } } } catch (err) { console.log('[ERROR] httpInterface -> startHtttpServer -> Error = ' + err.stack) } } function onBrowserRequest(httpRequest, httpResponse) { function getBody(callback) { // Gets the de body from a POST httpRequest to the web server try { let body = '' httpRequest.on('data', function (data) { body += data // Too much POST data //if (body.length > 1e6) { // httpRequest.connection.destroy() //} }) httpRequest.on('end', function () { callback(body) }) httpRequest.on('error', function (err) { console.log('[INFO] httpInterface -> onBrowserRequest -> getBody -> err = ' + err.stack) respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) }) } catch (err) { console.log('[INFO] httpInterface -> onBrowserRequest -> getBody -> err = ' + err.stack) respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } } let requestParameters = httpRequest.url.split('/') requestParameters = httpRequest.url.split('?') // Remove version information requestParameters = requestParameters[0].split('/') switch (requestParameters[1]) { case 'WEB3': { getBody(processRequest) async function processRequest(body) { try { let params = JSON.parse(body) switch (params.method) { case 'getNetworkClientStatus': { let serverResponse = await WEB3_SERVER.getNetworkClientStatus( params.host, params.port, params.interface ) respondWithContent(JSON.stringify(serverResponse), httpResponse) return } case 'createWalletAccount': { let serverResponse = await WEB3_SERVER.createWalletAccount( params.entropy ) respondWithContent(JSON.stringify(serverResponse), httpResponse) return } case 'getWalletBalances': { let serverResponse = await WEB3_SERVER.getWalletBalances( params.host, params.port, params.interface, params.walletDefinition ) respondWithContent(JSON.stringify(serverResponse), httpResponse) return } default: { respondWithContent(JSON.stringify({ error: 'Method ' + params.method + ' is invalid.' }), httpResponse) } } } catch (err) { console.log('[ERROR] httpInterface -> WEB3s -> Method call produced an error.') console.log('[ERROR] httpInterface -> WEB3s -> err.stack = ' + err.stack) console.log('[ERROR] httpInterface -> WEB3s -> Params Received = ' + body) let error = { result: 'Fail Because', message: err.message, stack: err.stack } respondWithContent(JSON.stringify(error), httpResponse) } } break } case 'CCXT': { getBody(processRequest) async function processRequest(body) { try { let params = JSON.parse(body) const ccxt = require('ccxt') switch (params.method) { case 'fetchMarkets': { const exchangeClass = ccxt[params.exchangeId] const exchangeConstructorParams = { 'timeout': 30000, 'enableRateLimit': true, verbose: false } let ccxtExchange = new exchangeClass(exchangeConstructorParams) let ccxtMarkets = [] if (ccxtExchange.has.fetchMarkets === true) { ccxtMarkets = await ccxtExchange.fetchMarkets() } respondWithContent(JSON.stringify(ccxtMarkets), httpResponse) return } case 'listExchanges': { let exchanges = [] for (let i = 0; i < ccxt.exchanges.length; i++) { let exchangeId = ccxt.exchanges[i] const exchangeClass = ccxt[exchangeId] const exchangeConstructorParams = { 'timeout': 30000, 'enableRateLimit': true, verbose: false } let ccxtExchange try { ccxtExchange = new exchangeClass(exchangeConstructorParams) } catch (err) { } if (ccxtExchange === undefined) { continue } if (ccxtExchange.has.fetchOHLCV === params.has.fetchOHLCV) { if (ccxtExchange.has.fetchMarkets === params.has.fetchMarkets) { if (ccxtExchange.timeframes['1m'] !== undefined) { let exchange = { name: ccxtExchange.name, id: ccxtExchange.id } exchanges.push(exchange) } } } } respondWithContent(JSON.stringify(exchanges), httpResponse) return } } let content = { err: global.DEFAULT_FAIL_RESPONSE // method not supported } } catch (err) { console.log('[INFO] httpInterface -> CCXT FetchMarkets -> Could not fetch markets.') let error = { result: 'Fail Because', message: err.message } respondWithContent(JSON.stringify(error), httpResponse) } } break } break case 'Webhook': { switch (requestParameters[2]) { // switch by command case 'Fetch-Messages': { let exchange = requestParameters[3] let market = requestParameters[4] /* Some validations */ if (exchange === undefined) { console.log('[WARN] httpInterface -> Webhook -> Fetch-Messages -> Message with no Exchange received -> messageReceived = ' + messageReceived) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } if (market === undefined) { console.log('[WARN] httpInterface -> Webhook -> Fetch-Messages -> Message with no market received -> messageReceived = ' + messageReceived) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } let key = exchange + '-' + market let webhookMessages = webhook.get(key) if (webhookMessages === undefined) { webhookMessages = [] } respondWithContent(JSON.stringify(webhookMessages), httpResponse) webhookMessages = [] webhook.set(key, webhookMessages) break } case 'New-Message': { getBody(processRequest) function processRequest(messageReceived) { let timestamp = (new Date()).valueOf() let source = requestParameters[3] let exchange = requestParameters[4] let market = requestParameters[5] /* Some validations */ if (source === undefined) { console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no Source received -> messageReceived = ' + messageReceived) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } if (exchange === undefined) { console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no Exchange received -> messageReceived = ' + messageReceived) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } if (market === undefined) { console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no market received -> messageReceived = ' + messageReceived) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } let key = exchange + '-' + market let webhookMessages = webhook.get(key) if (webhookMessages === undefined) { webhookMessages = [] } webhookMessages.push([timestamp, source, messageReceived]) webhook.set(key, webhookMessages) respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } break } } break } break case 'Docs': { switch (requestParameters[2]) { // switch by command case 'Save-Node-Schema': { getBody(processRequest) async function processRequest(body) { try { let docsSchema = JSON.parse(body) let project = requestParameters[3] let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Nodes' const fs = require('fs') fs.rmdir(filePath, { recursive: true }, onDirDeleted) function onDirDeleted(err) { if (err && err.code === 'EBUSY') { throw ('Can not delete the folder ' + filePath + ' because a file in it is open by some other program.') } try { fs.mkdirSync(filePath) } catch (err) { if (err.code !== 'EEXIST') { throw (err) } } for (let i = 0; i < docsSchema.length; i++) { let schemaDocument = docsSchema[i] let fileContent = JSON.stringify(schemaDocument, undefined, 4) let fileName = schemaDocument.type.toLowerCase() for (let j = 0; j < 10; j++) { fileName = fileName.replace(' ', '-') } fileName = fileName + '.json' fs.writeFileSync(filePath + '/' + fileName, fileContent) } respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } } catch (err) { console.log('[ERROR] httpInterface -> Docs -> Save-Node-Schema -> Method call produced an error.') console.log('[ERROR] httpInterface -> Docs -> Save-Node-Schema -> err.stack = ' + err.stack) console.log('[ERROR] httpInterface -> Docs -> Save-Node-Schema -> Params Received = ' + body) let error = { result: 'Fail Because', message: err.message, stack: err.stack } respondWithContent(JSON.stringify(error), httpResponse) } } break } case 'Save-Concept-Schema': { getBody(processRequest) async function processRequest(body) { try { let docsSchema = JSON.parse(body) let project = requestParameters[3] let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Concepts' const fs = require('fs') fs.rmdir(filePath, { recursive: true }, onDirDeleted) function onDirDeleted(err) { if (err && err.code === 'EBUSY') { throw ('Can not delete the folder ' + filePath + ' because a file in it is open by some other program.') } try { fs.mkdirSync(filePath) } catch (err) { if (err.code !== 'EEXIST') { throw (err) } } for (let i = 0; i < docsSchema.length; i++) { let schemaDocument = docsSchema[i] let fileContent = JSON.stringify(schemaDocument, undefined, 4) let fileName = schemaDocument.type.toLowerCase() for (let j = 0; j < 10; j++) { fileName = fileName.replace(' ', '-') } fileName = fileName + '.json' fs.writeFileSync(filePath + '/' + fileName, fileContent) } respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } } catch (err) { console.log('[ERROR] httpInterface -> Docs -> Save-Concept-Schema -> Method call produced an error.') console.log('[ERROR] httpInterface -> Docs -> Save-Concept-Schema -> err.stack = ' + err.stack) console.log('[ERROR] httpInterface -> Docs -> Save-Concept-Schema -> Params Received = ' + body) let error = { result: 'Fail Because', message: err.message, stack: err.stack } respondWithContent(JSON.stringify(error), httpResponse) } } break } case 'Save-Topic-Schema': { getBody(processRequest) async function processRequest(body) { try { let docsSchema = JSON.parse(body) let project = requestParameters[3] let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Topics' const fs = require('fs') fs.rmdir(filePath, { recursive: true }, onDirDeleted) function onDirDeleted(err) { if (err && err.code === 'EBUSY') { throw ('Can not delete the folder ' + filePath + ' because a file in it is open by some other program.') } try { fs.mkdirSync(filePath) } catch (err) { if (err.code !== 'EEXIST') { throw (err) } } for (let i = 0; i < docsSchema.length; i++) { let schemaDocument = docsSchema[i] let fileContent = JSON.stringify(schemaDocument, undefined, 4) let pageNumber = '00' + schemaDocument.pageNumber let fileName = schemaDocument.topic.toLowerCase() + '-' + pageNumber.substring(pageNumber.length - 3, pageNumber.length) + '-' + schemaDocument.type.toLowerCase() for (let j = 0; j < 10; j++) { fileName = fileName.replace(' ', '-') } fileName = fileName + '.json' fs.writeFileSync(filePath + '/' + fileName, fileContent) } respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } } catch (err) { console.log('[ERROR] httpInterface -> Docs -> Save-Topic-Schema -> Method call produced an error.') console.log('[ERROR] httpInterface -> Docs -> Save-Topic-Schema -> err.stack = ' + err.stack) console.log('[ERROR] httpInterface -> Docs -> Save-Topic-Schema -> Params Received = ' + body) let error = { result: 'Fail Because', message: err.message, stack: err.stack } respondWithContent(JSON.stringify(error), httpResponse) } } break } case 'Save-Book-Schema': { getBody(processRequest) async function processRequest(body) { try { let docsSchema = JSON.parse(body) let project = requestParameters[3] let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Books' const fs = require('fs') fs.rmdir(filePath, { recursive: true }, onDirDeleted) function onDirDeleted(err) { if (err && err.code === 'EBUSY') { throw ('Can not delete the folder ' + filePath + ' because a file in it is open by some other program.') } try { fs.mkdirSync(filePath) } catch (err) { if (err.code !== 'EEXIST') { throw (err) } } for (let i = 0; i < docsSchema.length; i++) { let schemaDocument = docsSchema[i] let fileContent = JSON.stringify(schemaDocument, undefined, 4) let fileName = schemaDocument.type.toLowerCase() for (let j = 0; j < 10; j++) { fileName = fileName.replace(' ', '-') } fileName = fileName + '.json' fs.writeFileSync(filePath + '/' + fileName, fileContent) } respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } } catch (err) { console.log('[ERROR] httpInterface -> Docs -> Save-Book-Schema -> Method call produced an error.') console.log('[ERROR] httpInterface -> Docs -> Save-Book-Schema -> err.stack = ' + err.stack) console.log('[ERROR] httpInterface -> Docs -> Save-Book-Schema -> Params Received = ' + body) let error = { result: 'Fail Because', message: err.message, stack: err.stack } respondWithContent(JSON.stringify(error), httpResponse) } } break } } break } break case 'App': { switch (requestParameters[2]) { // switch by command case 'Contribute': { try { const simpleGit = require('simple-git'); const options = { baseDir: process.cwd(), binary: 'git', maxConcurrentProcesses: 6, } const git = simpleGit(options) const commitMessage = unescape(requestParameters[3]) git .add('./*') .commit(commitMessage) .push('origin', 'in-app-documentation') respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } catch (err) { console.log('[ERROR] httpInterface -> App -> Contribute -> Method call produced an error.') console.log('[ERROR] httpInterface -> App -> Contribute -> err.stack = ' + err.stack) console.log('[ERROR] httpInterface -> App -> Contribute -> Params Received = ' + requestParameters[3]) let error = { result: 'Fail Because', message: err.message, stack: err.stack } respondWithContent(JSON.stringify(error), httpResponse) } break } } } break case 'LegacyPlotter.js': { respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/LegacyPlotter.js', httpResponse) } break case 'PlotterPanel.js': { respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/PlotterPanel.js', httpResponse) } break case 'Images': // This means the Images folder. { let path = global.env.PATH_TO_CLIENT + 'WebServer/Images/' + requestParameters[2] if (requestParameters[3] !== undefined) { path = path + '/' + requestParameters[3] } if (requestParameters[4] !== undefined) { path = path + '/' + requestParameters[4] } if (requestParameters[5] !== undefined) { path = path + '/' + requestParameters[5] } path = unescape(path) respondWithImage(path, httpResponse) } break case 'Icons': // This means the Icons folder under Projects. { let path = global.env.PATH_TO_PROJECTS + '/' + requestParameters[2] + '/Icons' if (requestParameters[3] !== undefined) { path = path + '/' + requestParameters[3] } if (requestParameters[4] !== undefined) { path = path + '/' + requestParameters[4] } if (requestParameters[5] !== undefined) { path = path + '/' + requestParameters[5] } path = unescape(path) respondWithImage(path, httpResponse) } break case 'GIFs': // This means the GIFs folder under Projects. { let path = global.env.PATH_TO_PROJECTS + '/' + requestParameters[2] + '/GIFs' if (requestParameters[3] !== undefined) { path = path + '/' + requestParameters[3] } if (requestParameters[4] !== undefined) { path = path + '/' + requestParameters[4] } if (requestParameters[5] !== undefined) { path = path + '/' + requestParameters[5] } path = unescape(path) respondWithImage(path, httpResponse) } break case 'PNGs': // This means the PNGs folder under Projects. { let path = global.env.PATH_TO_PROJECTS + '/' + requestParameters[2] + '/PNGs' if (requestParameters[3] !== undefined) { path = path + '/' + requestParameters[3] } if (requestParameters[4] !== undefined) { path = path + '/' + requestParameters[4] } if (requestParameters[5] !== undefined) { path = path + '/' + requestParameters[5] } path = unescape(path) respondWithImage(path, httpResponse) } break case 'favicon.ico': // This means the Scripts folder. { respondWithImage(global.env.PATH_TO_CLIENT + 'WebServer/Images/' + 'favicon.ico', httpResponse) } break case 'WebServer': // This means the WebServer folder. { respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/' + requestParameters[2], httpResponse) } break case 'externalScripts': // This means the WebServer folder. { respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/externalScripts/' + requestParameters[2], httpResponse) } break case 'Plotters': // This means the plotter folder, not to be confused with the Plotters script! { let project = requestParameters[2] let dataMine = requestParameters[3] let codeName = requestParameters[4] let moduleName = requestParameters[5] let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/' + 'Bots-Plotters-Code' + '/' + dataMine + '/plotters/' + codeName + '/' + moduleName respondWithFile(filePath, httpResponse) } break case 'ChartLayers': { respondWithFile(global.env.PATH_TO_UI + '/' + requestParameters[1] + '/' + requestParameters[2], httpResponse) } break case 'Files': { respondWithFile(global.env.PATH_TO_DATA_FILES + '/' + requestParameters[2], httpResponse) } break case 'Fonts': { respondWithFont(global.env.PATH_TO_FONTS + '/' + requestParameters[2], httpResponse) } break case 'ProjectNames': { let projects = getDirectories(global.env.PATH_TO_PROJECTS) respondWithContent(JSON.stringify(projects), httpResponse) } break case 'Schema': { sendSchema(global.env.PATH_TO_PROJECTS + '/' + requestParameters[2] + '/Schemas/', requestParameters[3]) } break case 'IconNames': { let projects = getDirectories(global.env.PATH_TO_PROJECTS) const fs = require('fs') let icons = [] let totalProjects = projects.length let projectCounter = 0 for (let i = 0; i < projects.length; i++) { let project = projects[i] const folder = global.env.PATH_TO_PROJECTS + '/' + project + '/Icons/' fs.readdir(folder, (err, files) => { for (let j = 0; j < files.length; j++) { let file = files[j] icons.push([project, file]) } projectCounter++ if (projectCounter === totalProjects) { respondWithContent(JSON.stringify(icons), httpResponse) } }) } } break case 'PluginFileNames': { let project = unescape(requestParameters[2]) let pluginType = unescape(requestParameters[3]) const fs = require('fs') let folder = global.env.PATH_TO_PROJECTS + '/' + project + '/Plugins/' + pluginType fs.readdir(folder, (err, files) => { respondWithContent(JSON.stringify(files), httpResponse) }) } break case 'LoadPlugin': { let project = unescape(requestParameters[2]) let pluginType = unescape(requestParameters[3]) let fileName = unescape(requestParameters[4]) let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Plugins/' + pluginType + '/' + fileName respondWithFile(filePath, httpResponse) } break case 'Workspace.js': { let fs = require('fs') try { let filePath = global.env.PATH_TO_DEFAULT_WORKSPACE + '/Getting-Started.json' fs.readFile(filePath, onFileRead) } catch (e) { console.log('[ERROR] Error reading the Workspace.', e) } function onFileRead(err, workspace) { if (err) { respondWithContent(undefined, httpResponse) } else { let responseContent = 'function getWorkspace(){ return ' + workspace + '}' respondWithContent(responseContent, httpResponse) } } } break case 'ListWorkspaces': { let allWorkspaces = [] let projects = getDirectories(global.env.PATH_TO_PROJECTS) let projectsCount = 0 for (let i = 0; i < projects.length; i++) { let project = projects[i] readPluginWorkspaces() function readPluginWorkspaces() { let dirPath = global.env.PATH_TO_PROJECTS + '/' + project + '/Plugins/Workspaces' try { let fs = require('fs') fs.readdir(dirPath, onDirRead) function onDirRead(err, fileList) { if (err) { console.log('[WARN] Error reading a directory content. filePath = ' + dirPath) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } else { let updatedFileList = [] for (let i = 0; i < fileList.length; i++) { let name = 'Plugin \u2192 ' + fileList[i] updatedFileList.push([project, name]) } allWorkspaces = allWorkspaces.concat(updatedFileList) projectsCount++ if (projectsCount === projects.length) { readMyWorkspaces() } return } } } catch (err) { console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath) console.log('[ERROR] err.stack = ' + err.stack) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } } } function readMyWorkspaces() { let dirPath = global.env.PATH_TO_MY_WORKSPACES try { let fs = require('fs') fs.readdir(dirPath, onDirRead) function onDirRead(err, fileList) { if (err) { // This happens the first time you run the software. respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } else { let updatedFileList = [] for (let i = 0; i < fileList.length; i++) { let name = fileList[i] updatedFileList.push(['', name]) } allWorkspaces = allWorkspaces.concat(updatedFileList) respondWithContent(JSON.stringify(allWorkspaces), httpResponse) return } } } catch (err) { console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath) console.log('[ERROR] err.stack = ' + err.stack) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } } } break case 'LoadMyWorkspace': { let fileName = unescape(requestParameters[2]) let filePath = global.env.PATH_TO_MY_WORKSPACES + '/' + fileName + '.json' respondWithFile(filePath, httpResponse) } break case 'SaveWorkspace': { getBody(processRequest) async function processRequest(body) { let fileContent = body let fileName = unescape(requestParameters[2]) let filePath = global.env.PATH_TO_MY_WORKSPACES + '/' + fileName + '.json' try { let fs = require('fs') let dir = global.env.PATH_TO_MY_WORKSPACES; /* Create Dir if it does not exist */ if (!fs.existsSync(dir)) { fs.mkdirSync(dir); } fs.writeFile(filePath, fileContent, onFileWritten) function onFileWritten(err) { if (err) { console.log('[ERROR] SaveWorkspace -> onFileWritten -> Error writting the Workspace file. fileName = ' + fileName) console.log('[ERROR] SaveWorkspace -> onFileWritten -> err.stack = ' + err.stack) let error = { result: 'Fail Because', message: err.message, stack: err.stack } respondWithContent(JSON.stringify(error), httpResponse) } else { respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } } } catch (err) { console.log('[ERROR] SaveWorkspace -> Error writting the Workspace file. fileName = ' + fileName) console.log('[ERROR] SaveWorkspace -> err.stack = ' + err.stack) let error = { result: 'Fail Because', message: err.message, stack: err.stack } respondWithContent(JSON.stringify(error), httpResponse) } } } break case 'ListFunctionLibraries': { returnProjectFolderFileList('Function-Libraries') } break case 'ProjectsSchema': { let path = global.env.PATH_TO_PROJECTS + '/' + 'ProjectsSchema.json' respondWithFile(path, httpResponse) } break case 'ListSpaceFiles': { let fs = require('fs') let allFiles = [] let projects = getDirectories(global.env.PATH_TO_PROJECTS) let dirCount = 0 let totalDirs = 0 for (let i = 0; i < projects.length; i++) { let project = projects[i] let dirPath = project + '/UI/Spaces' let spaces = getDirectories(global.env.PATH_TO_PROJECTS + '/' + dirPath) for (let j = 0; j < spaces.length; j++) { let space = spaces[j] readDirectory(dirPath + '/' + space) } function readDirectory(path) { try { totalDirs++ fs.readdir(global.env.PATH_TO_PROJECTS + '/' + path, onDirRead) let otherDirs = getDirectories(global.env.PATH_TO_PROJECTS + '/' + path) for (let m = 0; m < otherDirs.length; m++) { let otherDir = otherDirs[m] readDirectory(path + '/' + otherDir) } function onDirRead(err, fileList) { if (err) { respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) } else { let updatedFileList = [] for (let k = 0; k < fileList.length; k++) { let name = fileList[k] if (name.indexOf('.js') < 0) { continue } updatedFileList.push(path + '/' + name) } allFiles = allFiles.concat(updatedFileList) dirCount++ if (dirCount === totalDirs) { respondWithContent(JSON.stringify(allFiles), httpResponse) } } } } catch (err) { console.log('[ERROR] Error reading a directory content. filePath = ' + path) console.log('[ERROR] err.stack = ' + err.stack) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } } } } break case 'ListUtilitiesFiles': { returnProjectFolderFileList('Utilities') } break case 'ListGlobalFiles': { returnProjectFolderFileList('Globals') } break case 'Projects': { let path = '' for (let i = 2; i < 10; i++) { if (requestParameters[i] !== undefined) { let parameter = unescape(requestParameters[i]) path = path + '/' + parameter } } let filePath = global.env.PATH_TO_PROJECTS + path respondWithFile(filePath, httpResponse) } break case 'Storage': { respondWithFile(global.env.PATH_TO_DATA_STORAGE + '/' + httpRequest.url.substring(9), httpResponse) } break case 'main.css': { sendStyleSheet('main.css') } break case 'tutorial.css': { sendStyleSheet('tutorial.css') } break case 'docs.css': { sendStyleSheet('docs.css') } break case 'context-menu.css': { sendStyleSheet('context-menu.css') } break case 'credits.css': { sendStyleSheet('credits.css') } break case 'docs.css': { sendStyleSheet('docs.css') } break case 'font-awasome.css': { sendStyleSheet('font-awasome.css') } break case 'prism.css': { sendStyleSheet('prism.css') } break case 'ExecuteTerminalCommand': { let command = unescape(requestParameters[2]) executeTerminalCommand(command) } break default: { homePage() } } function returnProjectFolderFileList(projectFolderName) { { let allLibraries = [] let projects = getDirectories(global.env.PATH_TO_PROJECTS) let projectsCount = 0 for (let i = 0; i < projects.length; i++) { let project = projects[i] let dirPath = global.env.PATH_TO_PROJECTS + '/' + project + '/' + 'UI' + '/' + projectFolderName try { let fs = require('fs') fs.readdir(dirPath, onDirRead) function onDirRead(err, fileList) { if (err) { console.log('[WARN] Error reading a directory content. filePath = ' + dirPath) return } else { let updatedFileList = [] for (let i = 0; i < fileList.length; i++) { let name = fileList[i] updatedFileList.push([project, name]) } allLibraries = allLibraries.concat(updatedFileList) projectsCount++ if (projectsCount === projects.length) { respondWithContent(JSON.stringify(allLibraries), httpResponse) } return } } } catch (err) { console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath) console.log('[ERROR] err.stack = ' + err.stack) respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } } } } function executeTerminalCommand(command) { const util = require('util'); const exec = util.promisify(require('child_process').exec); async function lsWithGrep() { try { const { stdout, stderr } = await exec(command); console.log('stdout:', stdout); console.log('stderr:', stderr); } catch (err) { console.error(err.stack); }; }; lsWithGrep(); } function sendSchema(filePath, schemaType) { let fs = require('fs') if (schemaType === 'AppSchema') { let fileName = 'AppSchema.json' try { filePath = filePath + fileName fs.readFile(filePath, onFileRead) } catch (e) { console.log('[ERROR] Error reading the ' + fileName, e) } function onFileRead(err, schema) { if (err) { respondWithContent(undefined, httpResponse) } else { respondWithContent(schema, httpResponse) } } } else { try { let folder = '' switch (schemaType) { case 'DocsNodeSchema': { folder = 'Docs-Nodes' break } case 'DocsConceptSchema': { folder = 'Docs-Concepts' break } case 'DocsTopicSchema': { folder = 'Docs-Topics' break } case 'DocsBookSchema': { folder = 'Docs-Books' break } } let schemaArray = [] let fileList = fs.readdirSync(filePath + '/' + folder) for (let k = 0; k < fileList.length; k++) { let name = fileList[k] let fileContent = fs.readFileSync(filePath + '/' + folder + '/' + name) let schemaDocument = JSON.parse(fileContent) schemaArray.push(schemaDocument) } let schema = JSON.stringify(schemaArray) respondWithContent(schema, httpResponse) } catch (err) { console.log('Could not send Schema:', filePath, schemaType) console.log(err.stack) respondWithContent("[]", httpResponse) } } } function sendStyleSheet(fileName) { let fs = require('fs') try { let filePath = global.env.PATH_TO_CLIENT + 'WebServer/css/' + fileName fs.readFile(filePath, onFileRead) function onFileRead(err, file) { try { let fileContent = file.toString() fileContent = fileContent.replace('HTTP_INTERFACE_PORT', global.env.HTTP_INTERFACE_PORT) fileContent = fileContent.replace('HTTP_INTERFACE_PORT', global.env.HTTP_INTERFACE_PORT) fileContent = fileContent.replace('HTTP_INTERFACE_PORT', global.env.HTTP_INTERFACE_PORT) respondWithContent(fileContent, httpResponse, 'text/css') } catch (err) { console.log('[ERROR] httpInterface -> mainCSS -> File Not Found: ' + fileName + ' or Error = ' + err.stack) } } } catch (err) { console.log(err) } } function homePage() { if (requestParameters[1] === '') { let fs = require('fs') try { let fileName = global.env.PATH_TO_CLIENT + 'WebServer/index.html' fs.readFile(fileName, onFileRead) function onFileRead(err, file) { try { let fileContent = file.toString() fileContent = fileContent.replace('HTTP_INTERFACE_PORT', global.env.HTTP_INTERFACE_PORT) respondWithContent(fileContent, httpResponse) } catch (err) { console.log('[ERROR] httpInterface -> homePage -> File Not Found: ' + fileName + ' or Error = ' + err.stack) } } } catch (err) { console.log(err) } } else { respondWithFile(global.env.PATH_TO_UI + '/' + requestParameters[1], httpResponse) } } } function respondWithFile(fileName, httpResponse) { let fs = require('fs') if (fileName.indexOf('undefined') > 0) { console.log('[WRN] httpInterface -> respondWithFile -> Received httpRequest for undefined file. ') respondWithContent(undefined, httpResponse) } else { try { fs.readFile(fileName, onFileRead) function onFileRead(err, file) { if (!err) { respondWithContent(file.toString(), httpResponse) } else { //console.log('File requested not found: ' + fileName) respondWithContent(undefined, httpResponse) } } } catch (err) { returnEmptyArray() } } } function respondWithContent(content, httpResponse, contentType) { try { httpResponse.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1. httpResponse.setHeader('Pragma', 'no-cache') // HTTP 1.0. httpResponse.setHeader('Expires', '0') // Proxies. httpResponse.setHeader('Access-Control-Allow-Origin', '*') // Allows to access data from other domains. if (content !== undefined) { if (contentType !== undefined) { httpResponse.writeHead(200, { 'Content-Type': contentType }) } else { httpResponse.writeHead(200, { 'Content-Type': 'text/html' }) } httpResponse.write(content) } else { httpResponse.writeHead(404, { 'Content-Type': 'text/html' }) httpResponse.write('The specified key does not exist.') } httpResponse.end('\n') } catch (err) { returnEmptyArray(httpResponse) } } function respondWithImage(fileName, httpResponse) { let fs = require('fs') try { fs.readFile(fileName, onFileRead) function onFileRead(err, file) { if (err) { console.log('[ERROR] httpInterface -> respondWithImage -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack) return } try { httpResponse.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1. httpResponse.setHeader('Pragma', 'no-cache') // HTTP 1.0. httpResponse.setHeader('Expires', '0') // Proxies. httpResponse.setHeader('Access-Control-Allow-Origin', '*') // Allows to access data from other domains. httpResponse.writeHead(200, { 'Content-Type': 'image/png' }) httpResponse.end(file, 'binary') } catch (err) { console.log('[ERROR] httpInterface -> respondWithImage -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack) } } } catch (err) { console.log('[ERROR] httpInterface -> respondWithImage -> err = ' + err.stack) } } function respondWithFont(fileName, httpResponse) { let fs = require('fs') try { fs.readFile(fileName, onFileRead) function onFileRead(err, file) { try { if (err) { console.log('[ERROR] httpInterface -> respondWithBinary -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack) return } httpResponse.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1. httpResponse.setHeader('Pragma', 'no-cache') // HTTP 1.0. httpResponse.setHeader('Expires', '0') // Proxies. httpResponse.setHeader('Access-Control-Allow-Origin', '*') // Allows to access data from other domains. if (fileName.indexOf('2') < 0) { httpResponse.writeHead(200, { 'Content-Type': 'font/woff' }) } else { httpResponse.writeHead(200, { 'Content-Type': 'font/woff2' }) } httpResponse.end(file, 'binary') } catch (err) { console.log('[ERROR] httpInterface -> respondWithBinary -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack) } } } catch (err) { console.log('[ERROR] httpInterface -> respondWithBinary -> err = ' + err.stack) } } function returnEmptyArray(httpResponse) { try { httpResponse.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1. httpResponse.setHeader('Pragma', 'no-cache') // HTTP 1.0. httpResponse.setHeader('Expires', '0') // Proxies. httpResponse.writeHead(200, { 'Content-Type': 'text/html' }) httpResponse.write('[]') httpResponse.end('\n') } catch (err) { console.log('[ERROR] httpInterface -> returnEmptyArray -> err.stack ' + err.stack) } } function getDirectories(path) { const fs = require('fs') return fs.readdirSync(path).filter(function (file) { return fs.statSync(path + '/' + file).isDirectory(); }); } }