199 lines
5.0 KiB
JavaScript
Executable File
199 lines
5.0 KiB
JavaScript
Executable File
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('<html><body>');
|
|
for(var i = 0; i < list.length; ++i){
|
|
response.write('<a href='+request.url+'/'+list[i]+'>'+list[i]+'</a><br>');
|
|
}
|
|
response.write('</body></html>');
|
|
}
|
|
|
|
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('<html><body>Error: Resrouce not found</body></html>');
|
|
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
|
|
|
|
}
|