/* ---------------------------------------------------------------------------- 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 express = require('express') const bodyParser = require('body-parser') const busboy = require('connect-busboy') const fs = require('fs') const app = express() let url = '' const logger = require('../utils/logger.js') // const utils = require('../utils/utils.js') // const actions = require('../utils/actions.js') const listedFiles = './public/files' app.set('view engine', 'ejs') 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, '/*.mp4', 'video/mp4', 'stuff/video' function appGetFileType (app, wildcard, contentType, pageToRender) { app.get(wildcard, function (req, res) { let p = decodeURI(req.url) let fp = p if (p.includes('?')) { fp = p.split('?') fp.pop() fp = fp.join('/') } const fpath = './public/files' + fp if (!fs.existsSync(fpath)) { res.render('stuff/nofile', { missingFile: fpath, url }) return } if (req.query.stream || !pageToRender) { const stat = fs.statSync(fpath) const fileSize = stat.size const range = req.headers.range if (range) { const parts = range.replace(/bytes=/, '').split('-') const start = parseInt(parts[0], 10) const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1 const chunksize = (end - start) + 1 const file = fs.createReadStream(fpath, { start, end }) const head = { 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': contentType } res.writeHead(206, head) file.pipe(res) } else { const head = { 'Content-Length': fileSize, 'Content-Type': contentType } res.writeHead(200, head) fs.createReadStream(fpath).pipe(res) } } else { logger.LogReq(req) let fname = fpath.split('/') fname = fname.pop() res.render(pageToRender, { path: fp, fname, url, contentType, albumArt: GetAlbumArt(p) }) } }) } const fileTypes = [ ['/*.mp4', 'video/mp4', 'stuff/video'], ['/*.mkv', 'audio/x-matroska', 'stuff/video'], ['/*.mp3', 'audio/mpeg', 'stuff/audio'], ['/*.pdf', 'application/pdf'], ['/*.zip', 'application/zip'] ] function GetAlbumArt (path) { let tmp = path.split('.') tmp.pop() tmp = tmp.join('.').split('/') let last = tmp.pop() return tmp.join('/') + '/.' + last + '.png' } fileTypes.forEach((t) => { appGetFileType(app, t[0], t[1], t[2]) }) app.get('/*', function (req, res) { let parsedUrl = decodeURI(req.url) let curr = listedFiles + '/' + parsedUrl.substring('/'.length, parsedUrl.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) try { 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 stat = fs.statSync(curr + '/' + item) let fileSizeInBytes = stat['size'] res.size = Math.round(fileSizeInBytes / 1000000) res.path = relPath if (res.path[res.path.length - 1] !== '/') { res.path += '/' } res.path += item res.mtime = stat['mtime'].toLocaleString() res.isDir = stat.isDirectory() f.push(res) } }) res.render('stuff/folders', { folders: f, dirname: relPath, prevDir, url }) } else { let fileStream = fs.createReadStream(curr) fileStream.pipe(res) } } catch (e) { res.render('stuff/nofile', { missingFile: curr, url }) } }) // ----------------------------------------------------------------------------------------------- app.get('*', function (req, res) { res.status(404).render('shared/404') }) app.post('*', function (req, res) { res.status(404).render('shared/404') }) exports.app = app exports.setup = (x) => { url = x.url } logger.Log('Stuff module started', logger.GetColor('yellow'))