const geoip = require('geoip-country'); const fs = require('fs'); const mime = require('mime'); const CryptoJS = require("crypto-js"); const http = require('https'); const {config} = require('./config'); function getLastModified(headers){ var last = headers['last-modified'] if(last) return last; else return ''; } function getETAG(headers){ var etag = headers.etag if(etag) return etag else return ''; } function getHeaders(url){ return new Promise((resolve,reject)=>{ try{ var request = http.request(url, {method: 'HEAD'}, res =>{ //console.log(res); resolve(res.headers); }); request.end(); } catch(err){ reject(err.message); } }); } function validEmail(email){ const regex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return email.test(regex); } function validName(name){ } function validURL(url){ const regex = /^((https?):\/\/)?([w|W]{3}\.)+[a-zA-Z0-9\-\.]{3,}\.[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?$/; return regex.test(url); } function parseCookies (request) { var cookies = {}; if(request.headers && request.headers.cookie){ request.headers && request.headers.cookie.split(';').forEach(function(cookie) { var parts = cookie.match(/(.*?)=(.*)$/) cookies[ parts[1].trim() ] = (parts[2] || '').trim(); }); } return cookies; } //Return true if cookie exists, and decrypted SSID is valid function getSSID(request){ var cookies = parseCookies(request); if(cookies.ssid != undefined && cookies.ssid != null) var encrypted = cookies.ssid.toString(); else return {}; if(encrypted != null && encrypted != undefined && encrypted != ""){ //console.log("encrypted ssid cookie is " +encrypted); var decrpyted = decrypt(encrypted); //console.log('decrypted is '+decrpyted); var userdata = decrpyted.split(';'); var email = userdata[0]; var ip = userdata[1]; var date = userdata[2]; if(ip != request.socket.remoteAddress){ return {}; } else if( date > (new Date().getTime+config.cookie_timeout)){ return {}; } else{ return {"email":email,"ip":ip,"date":date}; } } else{ return {}; } } //Check to see if request IP is in allowed region function check_whitelist(whitelist){ var geo = geoip.lookup(whitelist.ip); if(geo != null) whitelist.country = geo.country; //Country whitelist if(!config.countries.includes(whitelist.country)) whitelist.stop = true; } //Serve a directory listing in HTML when a folder requested with no index. function response_write_dir(request, response ,systemPath){ response.writeHead(200, { 'Content-Type': 'text/html' }); var list = fs.readdirSync(systemPath); response.write(''); for(var i = 0; i < list.length; ++i){ response.write(''+list[i]+'
'); } response.write(''); } function serve_resource(request, response, whitelist){ var url = new URL(request.url,`http://${request.headers.host}`); var systemPath = config.root + url.pathname; var resType = (url.pathname.includes('.')) ? 'file':'dir'; var contentType = mime.getType(url.pathname); //Remove trailing '/'s while(systemPath.endsWith('/')){ systemPath = systemPath.substr(0,systemPath.length-1); } //Log for requests console.log('Request from '+request.socket.remoteAddress+':'+request.socket.remotePort+', ' +request.socket.remoteFamily +'\nFor resource '+url.pathname+'\nCountry: '+whitelist.country+'\tMethod: ' + request.socket.parser.incoming.method+'\n'); //If navigating to directory and index resource exists, serve index.html if(resType == 'dir' && fs.existsSync(systemPath+'/index.html')) systemPath = systemPath+'/index.html'; fs.readFile(systemPath, function(err, content) { if (err) { if(err.code == 'ENOENT'){ response.writeHead(404, { 'Content-Type': 'text/html' }); response.write('Error: Resrouce not found'); response.end(null, 'utf-8'); } else {//If reading a directory with no index.html, serve file list in HTML response_write_dir(request,response,systemPath); response.end(null, 'utf-8'); } } else { response.writeHead(200, { 'Content-Type': contentType }); response.end(content, 'utf-8'); } }); } function getPostData(request) { return new Promise((resolve, reject) => { try { let body = '' request.on('data', (chunk) => { body += chunk.toString() }) request.on('end', () => { resolve(body) }) } catch (err) { reject(err.message) } }) } function encrypt(string){ return CryptoJS.AES.encrypt(string,config.key).toString(); } function decrypt(string){ return CryptoJS.AES.decrypt(string, config.key).toString(CryptoJS.enc.Utf8); } module.exports = { check_whitelist, serve_resource, getPostData, encrypt, decrypt, getSSID, validEmail, validName, validURL, getHeaders, getLastModified, getETAG }