#!/usr/bin/env node const cmn = require("./modules/$common.js"); const express = require("express"); const http = require("http"); const socketio = require("socket.io"); const url = require("url"); const fs = require("fs"); const util = require("util"); const node_path = require("path"); const bodyParser = require("body-parser"); const basicAuth = require("basic-auth"); // const Logger = require("./logger"); if (process.argv.length > 3) { console.log("Pass optional port as first argument"); process.exit(1); } const PORT = process.argv.length == 3 ? +process.argv[2] : 80; const app = express(); const httpServer = http.Server(app); const io = socketio(httpServer); // const reqlogger = new Logger("request_log.txt"); const whatpulse = {"keys": "", "clicks": ""}; function refreshWhatpulse() { const url = "http://api.whatpulse.org/user.php?user=tomsmeding&format=json&formatted=yes"; http.get(url, function (res) { let body = ""; res.on("data", function (data) { body += data; }); res.on("end", function () { try { body = JSON.parse(body); } catch (e) { return; } whatpulse.keys = body.Keys/*.replace(/,/g, " ")*/; whatpulse.clicks = body.Clicks/*.replace(/,/g, " ")*/; }); }).on("error", function (err) { console.log(`Whatpulse request error: ${err.message}`); }); } setInterval(refreshWhatpulse, 6*3600*1000); //every 6 hours refreshWhatpulse(); // function simpleLogEscape(str) { // return str // .replace(/\\/g, "\\\\") // .replace(/\n/g, "\\n") // .replace(/ /g, "\\_"); // } // app.use(function (req, res, next) { // let line = simpleLogEscape(req.ip) + " " + // simpleLogEscape(req.method) + " " + // simpleLogEscape(req.hostname) + " " + // simpleLogEscape(req.url); // if (req.headers["dnt"]) line += " dnt=" + simpleLogEscape(req.headers["dnt"]); // if (req.headers["referer"]) line += " referer=" + simpleLogEscape(req.headers["referer"]); // reqlogger.log(line); // next(); // }); // app.use(function (req, res, next) { // console.log(req.subdomains); // next(); // }); app.use(bodyParser.text()); app.use(express.static("static")); const module_list = fs.readdirSync("modules").filter(function (f) { return ["$common.js", ".DS_Store"].indexOf(f) == -1 && f[0] != "$"; }); for (let i = 0; i < module_list.length; i++) { const mod = require("./modules/" + module_list[i] + "/" + module_list[i] + ".js"); mod(app, io, cmn.serverdir + "/modules/" + module_list[i]); console.log("Loaded module " + module_list[i]); } function requestFile(req, res, listdirs, path, origpath) { fname = cmn.webfilesdir + path; console.log("Requesting file " + fname); if (!fs.existsSync(fname)) { res.status(404).send("That file does not exist."); return; } const stats = fs.statSync(fname); if (stats.isFile()) { res.sendFile(fname); } else if (stats.isDirectory() && listdirs) { const items = fs .readdirSync(fname) .filter(function (f) { return f[0] != "."; }) .map(function (f) { try { if (fs.statSync(node_path.join(fname, f)).isDirectory()) return f + "/"; else return f; } catch (e) { return null; } }) .filter(function (f) { return f !== null; }); res.send( String(fs.readFileSync(cmn.serverdir + "/dirlisting.html")) .replace("", path) .replace("[/*LISTINGLISTING*/]", JSON.stringify(items)) ); } else if (stats.isDirectory() && fs.readdirSync(fname).indexOf("index.html") != -1) { if (origpath[origpath.length-1] != "/") origpath += "/"; res.redirect(301, origpath + "index.html"); } else { res.status(404).send("That file does not exist."); return; } } function makeUrlSafe(req, sliceLength) { const parsed = url.parse(req.url); const part = parsed.pathname.slice(sliceLength); if (part == "") return "/"; return part.replace(/\/\.+[^\/]*\//g, "/"); } app.get("/", function (req, res) { res.sendFile(cmn.serverdir + "/index.html"); // res.send( // String(fs.readFileSync(cmn.serverdir + "/index.html")) // .replace(//, whatpulse["keys"]) // .replace(//, whatpulse["clicks"]) // ); }); app.get(["/f/univq", "/f/univq/*"], cmn.authgen()); app.get(["/f", "/f/*"], function (req, res) { requestFile(req, res, false, unescape(makeUrlSafe(req, 2)), req.url); }); app.get(["/ff", "/ff/*"], cmn.authgen()); app.get(["/ff", "/ff/*"], function (req, res) { requestFile(req, res, true, unescape(makeUrlSafe(req, 3)), req.url); }); app.get("/.well-known/*", function (req, res) { requestFile(req, res, false, "/well-known" + unescape(makeUrlSafe(req, 12)), req.url); }); app.get("/google*.html", function (req, res) { const url = unescape(makeUrlSafe(req, 0)); if (url.match(/^\/google[0-9a-fA-F]*\.html$/)) { res.sendFile(__dirname + url); } else { res.status(404).send("That file does not exist."); } }); ["o", "k", "rip", "rip2"].forEach(function (target) { app.get("/" + target, function (req, res) { res.sendFile(cmn.webfilesdir + "/" + target + ".html"); }); app.get("/" + target + "/*", function (req, res) { res.set('Content-Type', 'text/html'); const msg = url.parse(req.url).pathname.slice(target.length + 2); res.send( String(fs.readFileSync(cmn.webfilesdir + "/" + target + ".html")) .replace("", cmn.simpleHTMLescape(msg)) ); }); }); app.get("/dr", function (req, res) { res.sendFile(cmn.webfilesdir + "/duckroll.html"); }); app.get(["/gpg", "/pgp", "/gpg.asc", "/pgp.asc"], function (req, res) { res.type("text/plain"); res.sendFile(cmn.webfilesdir + "/pgp.asc"); }); app.get("/tomsg", function (req, res) { res.sendFile(cmn.webfilesdir + "/tomsg.html"); }); app.get("/goioi", function (req, res) { res.sendFile(cmn.webfilesdir + "/goioi.html"); }); // app.get("/chat", function (req, res) { // res.redirect(301, "http://tomsmeding.com:81"); // }); // Error-handling middleware app.use(function (err, req, res, next) { const id = new Date().getTime().toString() + Math.random().toFixed(10).slice(2); console.error("Error caught in app: (id=" + id + ")"); console.error(err); console.error(err.stack); res.status(500).end("An internal error occurred; it has been logged with id " + id + ".\n"); }); const server = httpServer.listen(PORT, function () { const host = server.address().address; const port = server.address().port; console.log("Server listening at http://" + host + ":" + port); });