/* ---------------------------------------------------------------------------- Question Server GitLab: This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ------------------------------------------------------------------------- */ const startHTTPS = true const siteUrl = 'https://qmining.tk' // http(s)//asd.basd const ircURL = 'https://kiwiirc.com/nextclient/irc.sub.fm/#qmining' const express = require('express') const bodyParser = require('body-parser') const busboy = require('connect-busboy') const fs = require('fs') const app = express() const http = require('http') const https = require('https') const logger = require('./logger.js') const utils = require('./utils.js') const actions = require('./actions.js') const stat = require('./stat.js') const listedFiles = './public/files' const recivedFiles = 'public/recivedfiles' const uloadFiles = 'public/f' const staticFile = 'public/data/static' const dataFile = 'public/data.json' const msgFile = 'stats/msgs' // https://certbot.eff.org/ const privkeyFile = '/etc/letsencrypt/live/qmining.tk/privkey.pem' const fullchainFile = '/etc/letsencrypt/live/qmining.tk/fullchain.pem' const chainFile = '/etc/letsencrypt/live/qmining.tk/chain.pem' var certsLoaded = false if (startHTTPS && utils.FileExists(privkeyFile) && utils.FileExists(fullchainFile) && utils.FileExists( chainFile)) { try { const key = fs.readFileSync(privkeyFile, 'utf8') const cert = fs.readFileSync(fullchainFile, 'utf8') const ca = fs.readFileSync(chainFile, 'utf8') var certs = { key: key, cert: cert, ca: ca } certsLoaded = true } catch (e) { logger.Log('Error loading cert files!', logger.GetColor('redbg')) } } const port = 8080 const httpsPort = 8443 app.set('view engine', 'ejs') app.use(function (req, res, next) { res.on('finish', function () { logger.LogReq(req, true, res.statusCode) if (res.statusCode !== 404) { stat.LogStat(req.url) } }) next() }) app.use(express.static('public')) app.use(busboy({ limits: { fileSize: 10000 * 1024 * 1024 } })) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ limit: '5mb', extended: true })) app.use(bodyParser.json({ limit: '5mb' })) // -------------------------------------------------------------- app.get('/', function (req, res) { // req.hostname res.render('main', { siteurl: siteUrl, qa: actions.ProcessQA() }) res.end() }) app.get('/sio', function (req, res) { res.render('uload') res.end() }) app.get('/manual', function (req, res) { res.render('man') res.end() logger.LogReq(req) }) app.get('/public', function (req, res) { var response = '@Plz update :)' response += utils.ReadFile(staticFile) res.write(response) res.end() }) app.get('/static', function (req, res) { var response = '@Plz update :)' response += utils.ReadFile(staticFile) res.write(response) res.end() }) app.get('/legacy', function (req, res) { var f = utils.ReadFile(dataFile) var d = actions.LoadJSON(f) let qcount = 0 for (let i = 0; i < d.length; i++) { qcount += d.Subjects[i].length } let scount = d.length res.render('alldata', { data: d, scount: scount, qcount: qcount, siteurl: siteUrl }) logger.LogReq(req) }) app.post('/postfeedback', function (req, res) { res.redirect('back') logger.Log('New feedback message', logger.GetColor('bluebg'), true) utils.AppendToFile('\n\n' + logger.GetDateString() + ': ' + req.body.message_field, msgFile) }) app.get('/postfeedback', function (req, res) { // TODO: res.redirect("/"); or if needs this anyways, becouse /postfeedback post handler already // redirects res.render('main', { sdata: utils.ReadFile(staticFile) }) }) app.post('/isAdding', function (req, res) { res.end('OK') logger.LogReq(req) actions.ProcessIncomingRequest(req.body.datatoadd) utils.WriteBackup() }) app.get('/lred', function (req, res) { res.redirect('/legacy') res.end() logger.LogReq(req) }) app.get('/menuClick', function (req, res) { res.redirect('/') res.end() logger.LogReq(req) }) app.get('/irc', function (req, res) { res.redirect(ircURL) res.end() logger.LogReq(req) }) // all questions readable app.get('/allqr', function (req, res) { var f = utils.ReadFile(dataFile) var d = actions.LoadJSON(f) res.render('allqr', { d: d.toString().split('\n') }) logger.LogReq(req) }) app.get('/greasy', function (req, res) { res.redirect('https://greasyfork.org/en/scripts/38999-moodle-elearning-kmooc-test-help') res.end() logger.LogReq(req) }) app.get('/scriptgit', function (req, res) { res.redirect('https://gitlab.com/YourFriendlyNeighborhoodDealer/moodle-test-userscript') res.end() logger.LogReq(req) }) app.get('/servergit', function (req, res) { res.redirect('https://gitlab.com/YourFriendlyNeighborhoodDealer/question-node-server') res.end() logger.LogReq(req) }) function UploadFile (req, res, path, next) { var fstream req.pipe(req.busboy) req.busboy.on('file', function (fieldname, file, filename) { logger.Log('Uploading: ' + filename, logger.GetColor('blue')) utils.CreatePath(path, true) let d = new Date() let fn = d.getHours() + '' + d.getMinutes() + '' + d.getSeconds() + '_' + filename fstream = fs.createWriteStream(path + '/' + fn) file.pipe(fstream) fstream.on('close', function () { logger.Log('Upload Finished of ' + path + '/' + fn, logger.GetColor('blue')) next(fn) }) fstream.on('error', function (err) { console.log(err) res.end('something bad happened :s') }) }) } app.route('/fosuploader').post(function (req, res, next) { UploadFile(req, res, uloadFiles, (fn) => { res.redirect('/f/' + fn) }) }) app.route('/badtestsender').post(function (req, res, next) { UploadFile(req, res, recivedFiles, (fn) => { res.render('uploaded') }) logger.LogReq(req) }) // ----------------------------------------------------------------------------------------------- app.get('/stuff*', function (req, res) { let curr = listedFiles + '/' + req.url.substring('/stuff/'.length, req.url.length).split('?')[0] let relPath = curr.substring('./public/files'.length, curr.length) if (relPath[relPath.length - 1] !== '/') { relPath += '/' } let t = relPath.split('/') let prevDir = '' for (let i = 0; i < t.length - 2; i++) { prevDir += t[i] + '/' } // curr = curr.replace(/\//g, "/"); // relPath = relPath.replace(/\//g, "/"); logger.LogReq(req) if (fs.lstatSync(curr).isDirectory()) { if (curr[curr.length - 1] !== '/') { curr += '/' } let f = [] fs.readdirSync(curr).forEach((item) => { if (item[0] !== '.') { let res = { name: item } let stats = fs.statSync(curr + '/' + item) let fileSizeInBytes = stats['size'] res.size = Math.round(fileSizeInBytes / 1000000) res.path = relPath if (res.path[res.path.length - 1] !== '/') { res.path += '/' } res.path += item res.mtime = stats['mtime'].toLocaleString() f.push(res) } }) res.render('folders', { folders: f, dirname: relPath, prevDir }) } else { let fileStream = fs.createReadStream(curr) fileStream.pipe(res) } }) // ----------------------------------------------------------------------------------------------- app.get('*', function (req, res) { res.render('404') res.status(404) // utils.AppendToFile(logger.GetDateString() + ": " + "404 GET", logFile); }) app.post('*', function (req, res) { res.status(404) // utils.AppendToFile(logger.GetDateString() + ": " + "404 POST", logFile); }) var msg = '' stat.Load() const httpServer = http.createServer(app) httpServer.listen(port) msg += 'Server listening on port ' + port + ' (http)' if (startHTTPS && certsLoaded) { const httpsServer = https.createServer(certs, app) httpsServer.listen(httpsPort) msg += ', and ' + httpsPort + ' (https)...' } else { logger.Log('Cert files does not exists, starting http only!', logger.GetColor('redbg')) } logger.Log(msg, logger.GetColor('yellow')) logger.Log('Node version: ' + process.version)