var fs = require('fs-extra'); var http = require('http'); var path = require('path'); var swig = require('swig'); var urlm = require('url'); var exec = require('child_process').exec; var templates = {}; var lib; module.exports = Websrv; function Websrv(tlib) { this.lib = lib = tlib; Websrv.prototype.getTpls(); http.createServer((req, res) => { if(lib.cfg.websrv.wlip.hasOwnProperty(req.connection.remoteAddress)) { var filePath = '.' + req.url; var url = req.url.split("/")[1]; if(filePath == './') filePath = './index.html'; if(req.method == 'POST') { if(filePath == './git' && req.headers['x-gitlab-token'] == lib.cfg.websrv.gittoken) { var body = ''; req.on('data', (data) => { body += data; if(body.length > 1e6) req.connection.destroy(); }); req.on('end', () => { body = JSON.parse(body); var eventname = body.event_name; var autor = body.user_name; var branch = body.ref.split('/')[2]; if(branch === "master") { var commit = ""; try { commit = body.commits[body.commits.length-1].message.replace('\n','').trim(); } catch(ex) { commit = body.commits[body.commits.length-2].message.replace('\n','').trim(); } lib.bot.send( lib.cfg.main.debugchannel, eventname + ' from ' + autor + ' ('+commit+') in branch '+branch, 'n0xy' ); if( lib.cfg.main.debugchannel === '#f0ck' ) { exec('cd ../ & git pull', (error, stdout) => { if(error === null) { if(!lib.debug) lib.bot.send(lib.cfg.main.debugchannel, 'git pull suxxessfully.', 'n0xy'); else lib.log(stdout); } }); } } }); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('muh', 'utf-8'); } else res.writeHead(403); } else { var extname = String(path.extname(filePath)).toLowerCase(); var contentType = 'text/html'; var mimeTypes = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.png': 'image/png', '.jpg': 'image/jpg', '.gif': 'image/gif', '.mp3': 'audio/mpeg', '.mp4': 'video/mp4', '.webm': 'video/webm', '.ogg': 'audio/ogg', '.mov': 'video/quicktime' }; // Todo: hat hier nichts zu suchen! if(filePath == "./index.html") { // mainpage var tpl = swig.compile(templates.index); var data = { items: [], last: 10000 }; lib.sql.query("select `id`,`mime` from `f0ck`.`items` order by `id` desc limit 100", (err, rows, fields) => { rows.forEach((e,i,a) => { data.items.push({ "id": e.id, "mime": e.mime }); data.last = e.id; }); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(tpl(data), 'utf-8'); }); } else if(Number.isInteger(parseInt(url))) { // itempage var query = "select * from `f0ck`.`items` where `id` = ? limit 1; " // get item + "select `id` from `f0ck`.`items` where `id` = (select min(`id`) from `f0ck`.`items` where `id` > ?); " // get previous item + "select `id` from `f0ck`.`items` where `id` = (select max(`id`) from `f0ck`.`items` where `id` < ?)"; // get next item lib.sql.query(query, [url, url, url], (err, rows, fields) => { var tpl = swig.compile(templates.item); var data = { id: '', username: '', item: '', src: '', dest: '', mime: '', size: '', userchannel: '', usernetwork: '', thumb: null, next: null, prev: null }; if(rows[0].length) { var e = rows[0][0]; switch(e.mime) { case "image/png": case "image/jpeg": case "image/gif": data.item = 'image'; break; case "video/webm": case "video/mp4": case "video/quicktime": data.item = 'video'; break; case "audio/mpeg": case "audio/ogg": data.item = 'audio'; break; } data.id = e.id; data.username = e.username; data.srcurl = e.src; data.src = urlm.parse(e.src).hostname; data.thumb = (e.thumb != '' && e.thumb.match(/sndcdn\.com/i))?e.thumb:null; data.dest = e.dest; data.mime = e.mime; data.size = lib.formatSize(e.size); data.userchannel = e.userchannel; data.usernetwork = e.usernetwork; data.timestamp = new Date(e.stamp * 1000).toString(); if(rows[1].length) data.next = rows[1][0].id; if(rows[2].length) data.prev = rows[2][0].id; } res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(tpl(data), 'utf-8'); }); } else if(filePath == "./random") { lib.sql.query("select `id` from `f0ck`.`items` order by rand() limit 1", (err, rows, fields) => { res.writeHead(301, { 'Cache-Control': 'no-cache, public', 'Location': '/' + rows[0].id }); res.end(); }); } else if(filePath == "./how") { var tpl = swig.compile(templates.how); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(tpl(), 'utf-8'); } else if(filePath == "./contact") { var tpl = swig.compile(templates.contact); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(tpl(), 'utf-8'); } else if(filePath == "./scripts") { var tpl = swig.compile(templates.scripts); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(tpl(), 'utf-8'); } else if(filePath.match(/^\.\/(b|s|t)\/.*/)) { // file contentType = mimeTypes[extname]; switch(contentType) { case "video/webm": case "video/mp4": case "video/quicktime": case "audio/mpeg": case "audio/ogg": var start = 0; var end = 0; var range = req.headers['range']; var stat = fs.statSync(filePath); if(range != null) { start = parseInt(range.slice(range.indexOf('bytes=')+6, range.indexOf('-'))); end = parseInt(range.slice(range.indexOf('-')+1, range.length)); } if(isNaN(end) || end == 0) end = stat.size-1; if(start > end) return; res.writeHead(206, { 'Connection':'close', 'Content-Type':contentType, 'Content-Length':end - start, 'Content-Range':'bytes '+start+'-'+end+'/'+stat.size, 'Transfer-Encoding':'chunked' }); var stream = fs.createReadStream(filePath, { flags: 'r', start: start, end: end}); stream.pipe(res); break; default: fs.readFile(filePath, (error, content) => { if(error) { if(error.code == 'ENOENT') { res.writeHead(200, { 'Content-Type': contentType }); res.end('404 - f0ck you', 'utf-8'); } else { res.writeHead(500); res.end('Sorry, check with the site admin for error: '+error.code+' ..\n'); res.end(); } } else { res.writeHead(200, { 'Content-Type': contentType, 'Content-Length': content.length, 'Cache-Control': 'max-age=2592000, public' }); res.end(content, 'utf-8'); } }); break; } fs.readFile(filePath, (error, content) => { if(error) { if(error.code == 'ENOENT') { res.writeHead(200, { 'Content-Type': contentType }); res.end('404 - f0ck you', 'utf-8'); } else { res.writeHead(500); res.end('Sorry, check with the site admin for error: '+error.code+' ..\n'); res.end(); } } }); } else if(filePath.match(/^\.\/api/i)) { // api var url = filePath.split('/'); if(url[2] === undefined) { // Mainpage var query = "select * from `f0ck`.`items`"; lib.sql.query(query, (err, rows, fields) => { var items = []; rows.forEach((e,i,a) => { items.push({ 'id': e.id, 'mime': e.mime }); }); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(JSON.stringify(items), 'utf-8'); }); } else if(url[2] == "p" && Number.isInteger(parseInt(url[3]))) { // pagination var eps = 50; var id = url[3]; lib.sql.query("select * from `f0ck`.`items` where `id` < ? order by `id` desc limit ?", [id, eps], (err, rows, fields) => { var items = { "items": [], "last": id }; rows.forEach((e,i,a) => { items.items.push({ 'id': e.id, 'mime': e.mime }); items.last = e.id; }); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(JSON.stringify(items), 'utf-8'); }); } else if(Number.isInteger(parseInt(url[2]))) { // Item var query = "select * from `f0ck`.`items` where `id` = ? limit 1; " // get item + "select `id` from `f0ck`.`items` where `id` = (select min(`id`) from `f0ck`.`items` where `id` > ?); " // get previous item + "select `id` from `f0ck`.`items` where `id` = (select max(`id`) from `f0ck`.`items` where `id` < ?)"; // get next item lib.sql.query(query, [url[2], url[2], url[2]], (err, rows, fields) => { var data; if(rows[0].length) { var e = rows[0][0]; data = { id: e.id, username: e.username, src: e.src, dest: e.dest, mime: e.mime, size: e.size, userchannel: e.userchannel, usernetwork: e.usernetwork, next: null, prev: null }; if(rows[1].length) data.next = rows[1][0].id; if(rows[2].length) data.prev = rows[2][0].id; } else data = { error: 'nope' }; res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(JSON.stringify(data), 'utf-8'); }); } } else { // errorpage res.writeHead(404); res.end('404 - f0ck you', 'utf-8'); } } } else { res.writeHead(403); res.end('403 - forbidden'); } }).listen(lib.cfg.websrv.port); } Websrv.prototype.getTpls = () => { templates = { "index": fs.readFileSync("./s/index.tpl.html", "utf-8"), "item": fs.readFileSync("./s/item.tpl.html", "utf-8"), "how": fs.readFileSync("./s/how.tpl.html", "utf-8"), "contact": fs.readFileSync("./s/contact.tpl.html", "utf-8") }; };