From ad3ab133a5fa8ae065856102279116123e5b5854 Mon Sep 17 00:00:00 2001 From: Mystikfluu Date: Fri, 19 Aug 2022 23:37:24 +0200 Subject: [PATCH] move server_esm to server.js --- js/dms.js | 2 +- package-lock.json | 14 +- package.json | 2 +- server.js | 1778 ++++++++++++++++++++++----------------------- server_esm.js | 1036 -------------------------- 5 files changed, 891 insertions(+), 1941 deletions(-) delete mode 100644 server_esm.js diff --git a/js/dms.js b/js/dms.js index d081528..f01d183 100644 --- a/js/dms.js +++ b/js/dms.js @@ -248,7 +248,7 @@ async function createPost(username,text,time,specialtext,postid,isbot,reply_id,a } if(typeof decrypt == "function" && encryption_keys != "") { - text = decrypt(text,{packed:encryption_keys}) + text = decrypt(text,{packed:encryption_keys}).msg } newDiv.appendChild(newP) newDiv.innerHTML += filterPost(text) diff --git a/package-lock.json b/package-lock.json index 5460159..0c9528d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "helmet": "^5.1.1", "jimp": "^0.16.1", "mysql": "^2.18.1", - "unsafe_encrypt": "^1.0.3", + "unsafe_encrypt": "^1.0.4", "ws": "^8.8.1" } }, @@ -1608,9 +1608,9 @@ } }, "node_modules/unsafe_encrypt": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/unsafe_encrypt/-/unsafe_encrypt-1.0.3.tgz", - "integrity": "sha512-lAfx8aZqx+eyo/HDXZyy9RXRpAP7uVNeAK/Qv5sgetGL9swxJZdjptAl9iu4BMKaYynW1eHJ4nt0CguuTXhDXw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unsafe_encrypt/-/unsafe_encrypt-1.0.4.tgz", + "integrity": "sha512-n+pxzgOGVM0jslM+aQH20JMuyHXdmOKLUisA2s1XnT/vq4882iTfN+xmZCyfKbtDx/DZ4BizyL/Mw+xM9Ag58A==", "dependencies": { "readline-sync": "^1.4.10" } @@ -2921,9 +2921,9 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "unsafe_encrypt": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/unsafe_encrypt/-/unsafe_encrypt-1.0.3.tgz", - "integrity": "sha512-lAfx8aZqx+eyo/HDXZyy9RXRpAP7uVNeAK/Qv5sgetGL9swxJZdjptAl9iu4BMKaYynW1eHJ4nt0CguuTXhDXw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unsafe_encrypt/-/unsafe_encrypt-1.0.4.tgz", + "integrity": "sha512-n+pxzgOGVM0jslM+aQH20JMuyHXdmOKLUisA2s1XnT/vq4882iTfN+xmZCyfKbtDx/DZ4BizyL/Mw+xM9Ag58A==", "requires": { "readline-sync": "^1.4.10" } diff --git a/package.json b/package.json index d99f7a6..98e9842 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "helmet": "^5.1.1", "jimp": "^0.16.1", "mysql": "^2.18.1", - "unsafe_encrypt": "^1.0.3", + "unsafe_encrypt": "^1.0.4", "ws": "^8.8.1" }, "scripts": { diff --git a/server.js b/server.js index ea10c3e..0b43a47 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,30 @@ -const fs = require("fs") -const format = require("util").format +import http from "http"; +import https from "https"; +import * as express from "express"; +import useragent from "express-useragent"; +import fileUpload from "express-fileupload"; +import * as bodyParser from "body-parser"; +import cookieParser from "cookie-parser"; +import * as signature from "cookie-signature"; +import * as mysql from "mysql"; +import * as ws from "ws"; +import Jimp from "jimp"; +import SHA from "./extra_modules/SHA.js"; +import getIP from "./extra_modules/getip.js"; +import unsign from "./extra_modules/unsign.js"; +import { readFileSync, mkdir, existsSync, appendFile } from "fs"; +import { format } from "util"; +import { setup as optionssetup } from "./routes/api/options.js"; +import { setup as allsetup } from "./routes/api/all.js"; +import { setup as settingshandlersetup } from "./routes/api/settingshandler.js"; +import { setup as postsetup } from "./routes/api/post.js"; +import { setup as dmsPersonalMessagessetup } from "./routes/api/dms/PersonalMessages.js"; +import { setup as dmspostsetup } from "./routes/api/dms/post.js"; + +import { fileURLToPath } from 'url' +import { dirname } from 'path' +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) /** @@ -14,20 +39,20 @@ function ensureExists(path, mask, cb) { cb = mask; mask = 0o744; } - mkdir(path, mask, function(err) { + mkdir(path, mask, function (err) { if (err) { - if (err.code == 'EEXIST') cb(null); // Ignore the error if the folder already exists - else cb(err); // Something else went wrong - } else cb(null); // Successfully created folder + if (err.code == 'EEXIST') + cb(null); // Ignore the error if the folder already exists + else + cb(err); // Something else went wrong + } + else + cb(null); // Successfully created folder }); } - -const config = JSON.parse(readFileSync("server_config.json")) - -const time = Date.now() -const original_log = console.log - - +const config = JSON.parse(readFileSync("server_config.json")); +const time = Date.now(); +const original_log = console.log; /** * custom logging function * @param {number} level importance level if information @@ -35,119 +60,120 @@ const original_log = console.log * @return {undefined} returns nothing */ function log_info(level, ...info) { - let text = info - if(text == undefined || text.length == 0) { - text = level - level = 5 - } - if(config["logs"] && config["logs"]["level"] && config["logs"]["level"] >= level) { - let tolog = `[INFO] [${Date.now()}] : ${format(text)} \n` - original_log(tolog) //still has some nicer colors - ensureExists(__dirname + '/logs/', function(err) { - if(err) { - process.stderr.write(tolog) //just write it to stderr - } else { - appendFile(__dirname+"/logs/"+time,tolog,function(err){ - if(err){ - process.stderr.write(err) + let text = info; + if (text == undefined || text.length == 0) { + text = level; + level = 5; + } + if (config["logs"] && config["logs"]["level"] && config["logs"]["level"] >= level) { + let tolog = `[INFO] [${Date.now()}] : ${format(text)} \n`; + original_log(tolog); //still has some nicer colors + ensureExists(__dirname + '/logs/', function (err) { + if (err) { + process.stderr.write(tolog); //just write it to stderr } - }) - } - }); - } + else { + appendFile(__dirname + "/logs/" + time, tolog, function (err) { + if (err) { + process.stderr.write(err); + } + }); + } + }); + } +} +console.log = log_info; + +const WebSocket = ws.WebSocketServer; + +import {EventEmitter} from 'events'; +import merge from 'merge-descriptors'; + +/** + * Create an express application. + * + * @return {Function} + * @api public + */ + + function createApplication() { + var app = function(req, res, next) { + app.handle(req, res, next); + }; + + merge(app, EventEmitter.prototype, false); + merge(app, express.application, false); + + // expose the prototype that will get set on requests + app.request = Object.create(express.request, { + app: { configurable: true, enumerable: true, writable: true, value: app } + }) + + // expose the prototype that will get set on responses + app.response = Object.create(express.response, { + app: { configurable: true, enumerable: true, writable: true, value: app } + }) + + app.init(); + return app; } -console.log = log_info - - - -console.log(5,"starting up") - - - -const http = require('http'); -const https = require('https'); -const express = require("express"); -const useragent = require('express-useragent'); -const fileUpload = require('express-fileupload'); -const bodyParser = require("body-parser"); -const cookieParser = require('cookie-parser'); -const signature = require('cookie-signature') -const mysql = require('mysql'); -const WebSocket = require("ws").Server; -const Jimp = require('jimp'); - -console.log(5,"loaded dependencies") - const router = express.Router(); -const app = express(); - -const HASHES_DB = config.cookies.server_hashes -const HASHES_COOKIE = config.cookies.client_hashes -const HASHES_DIFF = HASHES_DB - HASHES_COOKIE - -const DID_I_FINALLY_ADD_HTTPS = true - +const app = createApplication(); +const HASHES_DB = config.cookies.server_hashes; +const HASHES_COOKIE = config.cookies.client_hashes; +const HASHES_DIFF = HASHES_DB - HASHES_COOKIE; +const DID_I_FINALLY_ADD_HTTPS = true; const con = mysql.createPool({ - connectionLimit : config.mysql.connections, - host: config.mysql.host, - user: config.mysql.user, - password: readFileSync(config.mysql.password_file).toString() + connectionLimit: config.mysql.connections, + host: config.mysql.host, + user: config.mysql.user, + password: readFileSync(config.mysql.password_file).toString() }); - -const dir = __dirname + "/" - -const cookiesecret = readFileSync("cookiesecret.txt").toString() - -const SHA = require("./extra_modules/SHA.js") - -const getIP = require("./extra_modules/getip.js") - +const dir = __dirname + "/"; +const cookiesecret = readFileSync("cookiesecret.txt").toString(); /** * quick function to convert data to base64 * @param {any} data data to encode in base64 * @return {string} base64 encoded data */ function b64(data) { - let buff = Buffer.from(data); - return buff.toString('base64'); + let buff = Buffer.from(data); + return buff.toString('base64'); } - /** * custom, bad random number generator * @param {number} seed seed for the number generator, defaults to current timestamp * @constructor */ function RNG(seed) { - if(!seed)seed = Date.now(); - this.seed = seed - - this.random = function(min,max) { - if(!min)min=0 - if(!max){ - max=min - min=0 - } - this.seed += Math.log(Math.abs(Math.sin(this.seed))*100) - return Math.abs(Math.sin(this.seed))*max + min - } - this.rand = function(min,max) { - return Math.floor(this.random(min,max)) - } + if (!seed) + seed = Date.now(); + this.seed = seed; + this.random = function (min, max) { + if (!min) + min = 0; + if (!max) { + max = min; + min = 0; + } + this.seed += Math.log(Math.abs(Math.sin(this.seed)) * 100); + return Math.abs(Math.sin(this.seed)) * max + min; + }; + this.rand = function (min, max) { + return Math.floor(this.random(min, max)); + }; } - /** * waits x ms * @param {number} ms amount of ms to sleep for * @return {promise} promise that gets resolved after x ms */ function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise(resolve => setTimeout(resolve, ms)); } - -const rand = new RNG() -const genstring_characters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +const rand = new RNG(); +const genstring_characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; const genstring_charactersLength = genstring_characters.length; /** * generates a semi-random string @@ -155,29 +181,28 @@ const genstring_charactersLength = genstring_characters.length; * @return {string} semi-random string generated */ function genstring(length) { - let result = ""; - for (let i = 0; i < length; i++) { - result += genstring_characters.charAt(rand.rand(genstring_charactersLength)); - } - return result; + let result = ""; + for (let i = 0; i < length; i++) { + result += genstring_characters.charAt(rand.rand(genstring_charactersLength)); + } + return result; } - - /** * handles client errors, used by expressJS */ function clientErrorHandler(err, req, res, next) { - if(err) { - if (req.xhr) { - res.status(200).send({ error: 'Something failed!' }); - } else { - console.log(1,err); + if (err) { + if (req.xhr) { + res.status(200).send({ error: 'Something failed!' }); + } + else { + console.log(1, err); + } + } + else { + next(); } - } else { - next() - } } - /** * utility function to get a key by its value in an object * @param {object} object object to get key from @@ -185,254 +210,229 @@ function clientErrorHandler(err, req, res, next) { * @return {any} key to the given value inside the object */ function getKeyByValue(object, value) { - return Object.keys(object).find(key => object[key] === value); + return Object.keys(object).find(key => object[key] === value); } - -const unsign = require("./extra_modules/unsign.js") - -var API_CALLS = {} -var API_CALLS_ACCOUNT = {} -var USER_CALLS = {} -var SESSIONS = {} -var REVERSE_SESSIONS = {} -var INDIVIDUAL_CALLS = {} +var API_CALLS = {}; +var API_CALLS_ACCOUNT = {}; +var USER_CALLS = {}; +var SESSIONS = {}; +var REVERSE_SESSIONS = {}; +var INDIVIDUAL_CALLS = {}; /** * clears current api call list (per IP) * @return {undefined} returns nothing */ function clear_api_calls() { - API_CALLS = {} + API_CALLS = {}; } /** * clears current api account call list (per account) * @return {undefined} returns nothing */ function clear_account_api_calls() { - API_CALLS_ACCOUNT = {} + API_CALLS_ACCOUNT = {}; } /** * clears current user file call list (per IP) * @return {undefined} returns nothing */ function clear_user_calls() { - USER_CALLS = {} + USER_CALLS = {}; } -setInterval(clear_api_calls, config.rate_limits.api.reset_time) -setInterval(clear_account_api_calls, config.rate_limits.api.reset_time) -setInterval(clear_user_calls, config.rate_limits.user.reset_time) - -function increaseIndividualCall(url,req) { //true = continue, false = ratelimit - let conf = config["rate_limits"]["individual"][url] - if(!conf) { - console.log(5,"uri not in individual ratelimiter",url); - return true; - } - if(!conf["enabled"])return true; - let ip = getIP(req) - if(INDIVIDUAL_CALLS[ip]==undefined)INDIVIDUAL_CALLS[ip] = {} - if(INDIVIDUAL_CALLS[ip][url]==undefined)INDIVIDUAL_CALLS[ip][url] = 0 - if(INDIVIDUAL_CALLS[ip][url] == 0) { - setTimeout(function(){ - INDIVIDUAL_CALLS[ip][url] = 0 - },conf["reset_time"]) - } - - INDIVIDUAL_CALLS[ip][url]++; - - if(INDIVIDUAL_CALLS[ip][url] >= conf["max"]){ - console.log(5,"ratelimiting someone on", url, INDIVIDUAL_CALLS[ip][url],conf["max"]); - return false; - } - - return true; -} - -function increaseAccountAPICall(req,res) { - let cookie = req.cookies.AUTH_COOKIE - if(!cookie){ - return true; - } - let unsigned = unsign.unsign(cookie,req,res) - if(!unsigned) { - - return true;//if there's no account, why not just ignore it - } - unsigned = decodeURIComponent(unsigned) - if(!unsigned)return false; - let values = unsigned.split(" ") - let username = values[0] - if(API_CALLS_ACCOUNT[username]==undefined)API_CALLS_ACCOUNT[username]=0 - if(API_CALLS_ACCOUNT[username] >= config.rate_limits.api.max_per_account) { - res.status(429) - res.send("You are sending way too many api calls!") - return false; - } - return true -} - -function increaseAPICall(req,res,next) { - let ip = getIP(req) - if(API_CALLS[ip]==undefined)API_CALLS[ip]=0 - if(API_CALLS[ip] >= config.rate_limits.api.max_without_session) { - if(REVERSE_SESSIONS[ip] && req.cookies.session !== REVERSE_SESSIONS[ip]) { //expected a session, but didn't get one - res.status(429) - res.send("You are sending way too many api calls!") - return +setInterval(clear_api_calls, config.rate_limits.api.reset_time); +setInterval(clear_account_api_calls, config.rate_limits.api.reset_time); +setInterval(clear_user_calls, config.rate_limits.user.reset_time); +function increaseIndividualCall(url, req) { + let conf = config["rate_limits"]["individual"][url]; + if (!conf) { + console.log(5, "uri not in individual ratelimiter", url); + return true; } - if(!req.cookies.session){ - let session - do { - session = genstring(300) - } while (SESSIONS[session] != undefined); - SESSIONS[session]=ip - REVERSE_SESSIONS[ip]=session - setTimeout(function(){ - SESSIONS[session]=undefined - REVERSE_SESSIONS[ip]=undefined - },50000) - res.cookie('session',session, { maxAge: 100000, httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - console.log(3,"sending session to " + ip); + if (!conf["enabled"]) + return true; + let ip = getIP(req); + if (INDIVIDUAL_CALLS[ip] == undefined) + INDIVIDUAL_CALLS[ip] = {}; + if (INDIVIDUAL_CALLS[ip][url] == undefined) + INDIVIDUAL_CALLS[ip][url] = 0; + if (INDIVIDUAL_CALLS[ip][url] == 0) { + setTimeout(function () { + INDIVIDUAL_CALLS[ip][url] = 0; + }, conf["reset_time"]); } - - } - if(API_CALLS[ip] >= config.rate_limits.api.max_with_session) { - res.status(429) - res.send("You are sending too many api calls!") - console.log(3,"rate limiting " + ip); - return false - } - API_CALLS[ip]++; - - if(!increaseAccountAPICall(req,res))return false; //can't forget account-based ratelimits - - if(next)next() - return true + INDIVIDUAL_CALLS[ip][url]++; + if (INDIVIDUAL_CALLS[ip][url] >= conf["max"]) { + console.log(5, "ratelimiting someone on", url, INDIVIDUAL_CALLS[ip][url], conf["max"]); + return false; + } + return true; } - -function increaseUSERCall(req,res,next) { - let ip = getIP(req) - if(USER_CALLS[ip]==undefined)USER_CALLS[ip]=0 - if(USER_CALLS[ip] >= config.rate_limits.user.max) { - res.status(429) - res.send("You are sending too many requests!") - console.log(2,"rate limiting " + ip); - return false - } - USER_CALLS[ip]++; - if(next)next() - return true +function increaseAccountAPICall(req, res) { + let cookie = req.cookies.AUTH_COOKIE; + if (!cookie) { + return true; + } + let unsigned = unsign.unsign(cookie, req, res); + if (!unsigned) { + return true; //if there's no account, why not just ignore it + } + unsigned = decodeURIComponent(unsigned); + if (!unsigned) + return false; + let values = unsigned.split(" "); + let username = values[0]; + if (API_CALLS_ACCOUNT[username] == undefined) + API_CALLS_ACCOUNT[username] = 0; + if (API_CALLS_ACCOUNT[username] >= config.rate_limits.api.max_per_account) { + res.status(429); + res.send("You are sending way too many api calls!"); + return false; + } + return true; } - -console.log(5,"loading routes") - +function increaseAPICall(req, res, next) { + let ip = getIP(req); + if (API_CALLS[ip] == undefined) + API_CALLS[ip] = 0; + if (API_CALLS[ip] >= config.rate_limits.api.max_without_session) { + if (REVERSE_SESSIONS[ip] && req.cookies.session !== REVERSE_SESSIONS[ip]) { //expected a session, but didn't get one + res.status(429); + res.send("You are sending way too many api calls!"); + return; + } + if (!req.cookies.session) { + let session; + do { + session = genstring(300); + } while (SESSIONS[session] != undefined); + SESSIONS[session] = ip; + REVERSE_SESSIONS[ip] = session; + setTimeout(function () { + SESSIONS[session] = undefined; + REVERSE_SESSIONS[ip] = undefined; + }, 50000); + res.cookie('session', session, { maxAge: 100000, httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); + console.log(3, "sending session to " + ip); + } + } + if (API_CALLS[ip] >= config.rate_limits.api.max_with_session) { + res.status(429); + res.send("You are sending too many api calls!"); + console.log(3, "rate limiting " + ip); + return false; + } + API_CALLS[ip]++; + if (!increaseAccountAPICall(req, res)) + return false; //can't forget account-based ratelimits + if (next) + next(); + return true; +} +function increaseUSERCall(req, res, next) { + let ip = getIP(req); + if (USER_CALLS[ip] == undefined) + USER_CALLS[ip] = 0; + if (USER_CALLS[ip] >= config.rate_limits.user.max) { + res.status(429); + res.send("You are sending too many requests!"); + console.log(2, "rate limiting " + ip); + return false; + } + USER_CALLS[ip]++; + if (next) + next(); + return true; +} +console.log(5, "loading routes"); app.use(useragent.express()); -app.use(fileUpload()) -app.use(bodyParser.json({ limit: "100mb" })); -app.use(bodyParser.urlencoded({ limit: "100mb", extended: true })); +app.use(fileUpload()); + +app.use(bodyParser.default.json({ limit: "100mb" })); +app.use(bodyParser.default.urlencoded({ limit: "100mb", extended: true })); app.use(clientErrorHandler); app.use(cookieParser(cookiesecret)); - var blocked_headers = [ - 'HTTP_VIA', - 'HTTP_X_FORWARDED_FOR', - 'HTTP_FORWARDED_FOR', - 'HTTP_X_FORWARDED', - 'HTTP_FORWARDED', - 'HTTP_CLIENT_IP', - 'HTTP_FORWARDED_FOR_IP', - 'VIA', - 'X_FORWARDED_FOR', - 'FORWARDED_FOR', - 'X_FORWARDED', - 'FORWARDED', - 'CLIENT_IP', - 'FORWARDED_FOR_IP', - 'HTTP_PROXY_CONNECTION' -] - -if(!config.disallow_proxies_by_headers) { - blocked_headers = [] + 'HTTP_VIA', + 'HTTP_X_FORWARDED_FOR', + 'HTTP_FORWARDED_FOR', + 'HTTP_X_FORWARDED', + 'HTTP_FORWARDED', + 'HTTP_CLIENT_IP', + 'HTTP_FORWARDED_FOR_IP', + 'VIA', + 'X_FORWARDED_FOR', + 'FORWARDED_FOR', + 'X_FORWARDED', + 'FORWARDED', + 'CLIENT_IP', + 'FORWARDED_FOR_IP', + 'HTTP_PROXY_CONNECTION' +]; +if (!config.disallow_proxies_by_headers) { + blocked_headers = []; } - -app.use(function(req,res,next) { - res.set("X-XSS-Protection","1; mode=block") - next() -}) - -if(DID_I_FINALLY_ADD_HTTPS) { - - //auto redirect to https - app.use((req, res, next) => { - if(req.secure){ - //already secure - next() - } else { - //redirect to https - res.redirect('https://' + req.headers.host + req.url) - } - }) +app.use(function (req, res, next) { + res.set("X-XSS-Protection", "1; mode=block"); + next(); +}); +if (DID_I_FINALLY_ADD_HTTPS) { + //auto redirect to https + app.use((req, res, next) => { + if (req.secure) { + //already secure + next(); + } + else { + //redirect to https + res.redirect('https://' + req.headers.host + req.url); + } + }); } - -app.use("/*",function(req,res,next){ - res.set("x-powered-by","ipost") - for (let i = 0; i < blocked_headers.length; i++) { - if(req.header(blocked_headers[i])!=undefined) { - res.json({"error":"we don't allow proxies on our website."}) - return +app.use("/*", function (req, res, next) { + res.set("x-powered-by", "ipost"); + for (let i = 0; i < blocked_headers.length; i++) { + if (req.header(blocked_headers[i]) != undefined) { + res.json({ "error": "we don't allow proxies on our website." }); + return; + } } - } - let fullurl = req.baseUrl + req.path - if(fullurl != "/") { - fullurl = fullurl.substring(0,fullurl.length-1) - } - if(!increaseIndividualCall(fullurl,req)){ - res.status(429) - res.json({"error":"you are sending too many requests!"}) - return - } - - next() -}) - -router.get("/",function(req,res) { - if(!increaseUSERCall(req,res))return - res.sendFile(dir+"views/index.html") -}) - -console.log(5,"finished loading user routes, starting with api routes") - + let fullurl = req.baseUrl + req.path; + if (fullurl != "/") { + fullurl = fullurl.substring(0, fullurl.length - 1); + } + if (!increaseIndividualCall(fullurl, req)) { + res.status(429); + res.json({ "error": "you are sending too many requests!" }); + return; + } + next(); +}); +router.get("/", function (req, res) { + if (!increaseUSERCall(req, res)) + return; + res.sendFile(dir + "views/index.html"); +}); +console.log(5, "finished loading user routes, starting with api routes"); /* START /API/* */ - var wss; - var commonfunctions = { - increaseAPICall, - increaseUSERCall, - increaseAccountAPICall, - increaseIndividualCall, - wss, - genstring -} - -import {setup as optionssetup} from "./routes/api/options.js" -import {setup as allsetup} from "./routes/api/all.js" -import {setup as settingshandlersetup} from "./routes/api/settingshandler.js" -import {setup as postsetup} from "./routes/api/post.js" -import {setup as dmsPersonalMessagessetup} from "./routes/api/dms/PersonalMessages.js" -import {setup as dmspostsetup} from "./routes/api/dms/post.js" - - -optionssetup(router,con,commonfunctions) -allsetup(router,con,commonfunctions) -settingshandlersetup(router,con,commonfunctions) -postsetup(router,con,commonfunctions) -dmsPersonalMessagessetup(router,con,commonfunctions) -dmspostsetup(router,con,commonfunctions) - + increaseAPICall, + increaseUSERCall, + increaseAccountAPICall, + increaseIndividualCall, + wss, + genstring +}; +optionssetup(router, con, commonfunctions); +allsetup(router, con, commonfunctions); +settingshandlersetup(router, con, commonfunctions); +postsetup(router, con, commonfunctions); +dmsPersonalMessagessetup(router, con, commonfunctions); +dmspostsetup(router, con, commonfunctions); // const toLoad = [ // "api/options.js", // "api/all.js", @@ -440,611 +440,597 @@ dmspostsetup(router,con,commonfunctions) // "api/post.js", // "api/dms/PersonalMessages.js", // "api/dms/post.js", - // ] - // for (let i = 0; i < toLoad.length; i++) { // require("./routes/"+toLoad[i]).setup(router,con,commonfunctions) // } - // let options = require("./routes/api/options.js") // options.setup(router,con,commonfunctions) - // let apiALL = require("./routes/api/all.js") // apiALL.setup(router,con,commonfunctions) - // let settingshandler = require("./routes/api/settingshandler.js") // settingshandler.setup(router,con,commonfunctions) - -router.get("/api/search", async function(req,res) { - res.set("Access-Control-Allow-Origin","") - let type = req.query.type - let arg = encodeURIComponent(req.query.selector) - if(type=="user") { - let sql = `select User_Name,User_Bio,User_Avatar from ipost.users where User_Name like ? limit 10;` - con.query(sql, [`%${arg}%`], function (err, result) { - if (err) throw err; - if(result[0] && result[0].User_Name) { - res.json(result) - } else { - res.json({"error":"there is no such user!"}) - } - }); - }else if (type=="post") { - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id from ipost.posts where post_text like ? and (post_receiver_name is null or post_receiver_name = 'everyone') order by post_id desc limit 20;` - con.query(sql, [`%${arg}%`], function (err, result) { - if (err) throw err; - if(result[0]) { - res.json(result) - } else { - res.json({"error":"there is no such post!"}) - } - }); - } else { - res.json({"error":"invalid type passed along, expected `user` or `post`"}) - } -}) - -router.post("/api/setavatar",function(req,res) { - res.set("Access-Control-Allow-Origin","") - if (!req.files || Object.keys(req.files).length === 0) { - return res.status(400).send('No files were uploaded. (req.files)'); - } - let avatar = req.files.avatar; - if(!avatar) { - return res.status(400).send('No files were uploaded. (req.files.)'); - } - - let DOSbuf = Buffer.from( 'ffd8ffc1f151d800ff51d800ffdaffde', 'hex' ); //causes DOS - if(avatar.data.includes(DOSbuf)) { - console.log(3,"DOS image was caught") - return res.status(400).send('No files were uploaded. (req.files.)'); - } - //DOS introduced through jimp (uses jpeg-js) - - const avatars = __dirname + '/avatars/' - ensureExists(avatars, function(err) { - if(err) { - return res.status(500).json({"error":"there's been an internal server error."}) - } - if(res.locals.avatar) { - unlinkSync(avatars + res.locals.avatar) - } - let filename = genstring(96) + ".png" - while(existsSync(avatars + "/" + filename) || filename == ".png") { - console.log(5,"already have file: ",filename); - original_log("already have file: ",filename) - filename = genstring(96) + ".png" - } - avatar.mv(avatars+"temp_"+filename,function(err) { - if(err) { - return res.status(500).json({"error":"there's been an internal server error."}) - } - Jimp.read(avatars+"temp_"+filename).then(function(image){ - image.resize(100, 100) - image.write(avatars+filename) - let sql = `update ipost.users set User_Avatar=? where User_Name=?` - con.query(sql, [filename,encodeURIComponent(res.locals.username)], function (err, result) { - if (err) throw err; - res.json({"success":"updated avatar"}) - unlinkSync(avatars+"temp_"+filename) +router.get("/api/search", async function (req, res) { + res.set("Access-Control-Allow-Origin", ""); + let type = req.query.type; + let arg = encodeURIComponent(req.query.selector); + if (type == "user") { + let sql = `select User_Name,User_Bio,User_Avatar from ipost.users where User_Name like ? limit 10;`; + con.query(sql, [`%${arg}%`], function (err, result) { + if (err) + throw err; + if (result[0] && result[0].User_Name) { + res.json(result); + } + else { + res.json({ "error": "there is no such user!" }); + } }); - }) - }) - }) -}) - -router.get("/api/getuser",async function(req,res) { - res.json({"username":res.locals.username,"bio":res.locals.bio,"avatar":res.locals.avatar}) -}) - -router.get("/api/getalluserinformation",async function(req,res) { - res.set("Access-Control-Allow-Origin","") //we don't want that here - let unsigned = unsign.getunsigned(req,res) - if(!unsigned)return - unsigned = decodeURIComponent(unsigned) - let sql = `select * from ipost.users where User_Name=? and User_PW=?;` - let values = unsigned.split(" ") - values[1] = SHA.SHA256(values[1],values[0],HASHES_DIFF) - con.query(sql, values, function (err, result) { - if (err) throw err; - if(result[0] && result[0].User_Name && result[0].User_Name == values[0]) { - res.status(200) - res.json(result[0]) - } else { - res.status(400) - res.json({"error":"you cannot access the api without being logged in"}) } - }); -}) - -router.get("/api/getotheruser",async function(req,res) { - res.set("Access-Control-Allow-Origin","*") - let username = req.query.user - - let sql = `select User_Name,User_Bio,User_Avatar,User_PublicKey from ipost.users where User_Name=?;` - con.query(sql, [username], function (err, result) { - if (err) throw err; - if(result[0] && result[0].User_Name && result[0].User_Name == username) { - res.json({"username":username,"bio":result[0].User_Bio,"avatar":result[0].User_Avatar,"publicKey": result[0].User_PublicKey}) - } else { - res.json({"error":"there is no such user!"}) + else if (type == "post") { + let sql = `select post_user_name,post_text,post_time,post_special_text,post_id from ipost.posts where post_text like ? and (post_receiver_name is null or post_receiver_name = 'everyone') order by post_id desc limit 20;`; + con.query(sql, [`%${arg}%`], function (err, result) { + if (err) + throw err; + if (result[0]) { + res.json(result); + } + else { + res.json({ "error": "there is no such post!" }); + } + }); } - }); -}) - - - -router.get("/api/getPosts/*", async function(req,res) { - res.set("Access-Control-Allow-Origin","") - res.redirect("/api/getPosts") -}) - -router.get("/api/getPosts", async function(req,res) { - res.set("Access-Control-Allow-Origin","*") - if(req.query.channel != undefined) { - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where post_receiver_name = ? group by post_id order by post_id desc limit 30;` - con.query(sql, [encodeURIComponent(req.query.channel)], function (err, result) { - if (err) throw err; - res.json(result) - }); - } else { //fallback - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where (post_receiver_name is null or post_receiver_name = 'everyone') group by post_id order by post_id desc limit 30;` - con.query(sql, [], function (err, result) { - if (err) throw err; - res.json(result) - }); - } -}) - -router.get("/api/getPostsLowerThan", async function(req,res) { - res.set("Access-Control-Allow-Origin","*") - if(req.query.channel != undefined) { - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where ((post_receiver_name = ?) and (post_id < ?)) group by post_id order by post_id desc limit 30;` - con.query(sql, [encodeURIComponent(req.query.channel),req.query.id], function (err, result) { - if (err) throw err; - res.json(result) - }); - } else { //fallback - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where ((post_receiver_name is null or post_receiver_name = 'everyone') and (post_id < ?)) group by post_id order by post_id desc limit 30;` - con.query(sql, [req.query.id], function (err, result) { - if (err) throw err; - res.json(result) - }); - } -}) - -router.get("/api/getPost", async function(req,res) { - res.set("Access-Control-Allow-Origin","*") - let arg = req.query.id - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id,post_receiver_name from ipost.posts where post_id=?;` - con.query(sql, [arg], function (err, result) { - if (err) throw err; - if(result[0]) { - res.set('Cache-Control', 'public, max-age=2592000'); //cache it for one month-ish - res.json(result[0]) - } else { - res.json({"error":"there is no such post!"}) + else { + res.json({ "error": "invalid type passed along, expected `user` or `post`" }); } - }); -}) - - - -router.get("/api/getChannels", async function(req,res) { - res.set("Access-Control-Allow-Origin","*") - let sql = `select post_receiver_name from ipost.posts where post_is_private = '0' group by post_receiver_name;` - con.query(sql, [], function (err, result) { - if (err) throw err; - res.json(result) - }); -}) - -router.post("/api/setBio", async function(req,res) { - res.set("Access-Control-Allow-Origin","") - let bio = req.body.Bio - if(!bio){ - res.status(400) - res.json({"error":"no bio set!"}) - return - } - bio = encodeURIComponent(bio) - if(100 < bio.length) { - res.status(400) - res.json({"error":"the bio is too long!"}) - return - } - let sql = `update ipost.users set User_Bio=? where User_Name=?` - con.query(sql, [bio,encodeURIComponent(res.locals.username)], function (err, result) { - if (err) throw err; - res.json({"success":"updated bio"}) - }); -}) - -router.post("/api/changePW", async function(req,res) { - res.set("Access-Control-Allow-Origin","") - if((typeof req.body.newPW) != "string") { - res.json({"error":"incorrect password"}) - return - } - if((typeof req.body.currentPW) != "string") { - res.json({"error":"incorrect password"}) - return - } - if(req.body.newPW.length < 10) { - res.status(400) - res.json({"error":"password is too short"}) - return - } - - let hashed_pw = SHA.SHA256(req.body.currentPW,res.locals.username,HASHES_DB) - let hashed_new_pw = SHA.SHA256(req.body.newPW,res.locals.username,HASHES_DB) - - let sql = `select * from ipost.users where User_Name=? and User_PW=?;` - let values = [res.locals.username,hashed_pw] - con.query(sql, values, function (err, result) { - if (err) throw err; - if(result[0] && result[0].User_Name && result[0].User_Name == res.locals.username) { - let sql = `update ipost.users set User_PW=? where User_Name=? and User_PW=?;` - let values = [hashed_new_pw,res.locals.username,hashed_pw] - con.query(sql, values, function (err, result) { - if (err) throw err; - let ip = getIP(req) - let setTo = res.locals.username + " " + SHA.SHA256(req.body.newPW,res.locals.username,HASHES_COOKIE) - let cookiesigned = signature.sign(setTo, cookiesecret+ip); - res.cookie('AUTH_COOKIE',cookiesigned, { maxAge: Math.pow(10,10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - res.json({"success":"successfully changed password"}) - }) - } else { - res.json({"error":"invalid password"}) +}); +router.post("/api/setavatar", function (req, res) { + res.set("Access-Control-Allow-Origin", ""); + if (!req.files || Object.keys(req.files).length === 0) { + return res.status(400).send('No files were uploaded. (req.files)'); } - sent_res = true - }); - setTimeout(function(){if(!sent_res)res.json({"error":"timeout"})},3000); -}) - -router.post("/api/changeUsername", async function(req,res) { - res.set("Access-Control-Allow-Origin","") - if((typeof req.body.newUsername) != "string") { - res.status(400) - res.json({"error":"incorrect username"}) - return - } - if((typeof req.body.currentPW) != "string") { - res.status(400) - res.json({"error":"incorrect password"}) - return - } - if(100 < req.body.newUsername.length) { - res.status(400) - res.json({"error":"username is too long"}) - return - } - - if(req.body.newUsername == res.locals.username) { - res.status(400) - res.json({"error":"username can't be the current one"}) - return - } - - let hashed_pw = SHA.SHA256(req.body.currentPW,res.locals.username,HASHES_DB) - let hashed_new_pw = SHA.SHA256(req.body.currentPW,req.body.newUsername,HASHES_DB) - - let sql = `select * from ipost.users where User_Name=?;` //check if pw is correct - let values = [res.locals.username] - con.query(sql, values, function (err, result) { - if (err) throw err; - if(result[0] && result[0].User_PW == hashed_pw) { - let sql = `select * from ipost.users where User_Name=?;` //check if newUsername isn't already used - let values = [req.body.newUsername] - con.query(sql, values, function (err, result) { - if (err) throw err; - if(result[0]) { - res.json({"error":"user with that username already exists"}) - return + let avatar = req.files.avatar; + if (!avatar) { + return res.status(400).send('No files were uploaded. (req.files.)'); + } + let DOSbuf = Buffer.from('ffd8ffc1f151d800ff51d800ffdaffde', 'hex'); //causes DOS + if (avatar.data.includes(DOSbuf)) { + console.log(3, "DOS image was caught"); + return res.status(400).send('No files were uploaded. (req.files.)'); + } + //DOS introduced through jimp (uses jpeg-js) + const avatars = __dirname + '/avatars/'; + ensureExists(avatars, function (err) { + if (err) { + return res.status(500).json({ "error": "there's been an internal server error." }); } - - let sql = `update ipost.users set User_PW=?,User_Name=? where User_Name=? and User_PW=?;` //change username in users - let values = [hashed_new_pw,req.body.newUsername,res.locals.username,hashed_pw] - con.query(sql, values, function (err, result) { - if (err) throw err; - let ip = getIP(req) - let setTo = req.body.newUsername + " " + SHA.SHA256(req.body.currentPW,req.body.newUsername,HASHES_COOKIE) - let cookiesigned = signature.sign(setTo, cookiesecret+ip); - res.cookie('AUTH_COOKIE',cookiesigned, { maxAge: Math.pow(10,10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - //updated username in the users table, but not yet on posts - let sql = `update ipost.posts set post_user_name=? where post_user_name=?;` //change username of every past post sent - let values = [req.body.newUsername,res.locals.username,hashed_pw] - con.query(sql, values, function (err, result) { - res.json({"success":"successfully changed username"}) //done - }); - }) - }) - } else { - res.json({"error":"invalid password"}) + if (res.locals.avatar) { + unlinkSync(avatars + res.locals.avatar); + } + let filename = genstring(96) + ".png"; + while (existsSync(avatars + "/" + filename) || filename == ".png") { + console.log(5, "already have file: ", filename); + original_log("already have file: ", filename); + filename = genstring(96) + ".png"; + } + avatar.mv(avatars + "temp_" + filename, function (err) { + if (err) { + return res.status(500).json({ "error": "there's been an internal server error." }); + } + Jimp.read(avatars + "temp_" + filename).then(function (image) { + image.resize(100, 100); + image.write(avatars + filename); + let sql = `update ipost.users set User_Avatar=? where User_Name=?`; + con.query(sql, [filename, encodeURIComponent(res.locals.username)], function (err, result) { + if (err) + throw err; + res.json({ "success": "updated avatar" }); + unlinkSync(avatars + "temp_" + filename); + }); + }); + }); + }); +}); +router.get("/api/getuser", async function (req, res) { + res.json({ "username": res.locals.username, "bio": res.locals.bio, "avatar": res.locals.avatar }); +}); +router.get("/api/getalluserinformation", async function (req, res) { + res.set("Access-Control-Allow-Origin", ""); //we don't want that here + let unsigned = unsign.getunsigned(req, res); + if (!unsigned) + return; + unsigned = decodeURIComponent(unsigned); + let sql = `select * from ipost.users where User_Name=? and User_PW=?;`; + let values = unsigned.split(" "); + values[1] = SHA.SHA256(values[1], values[0], HASHES_DIFF); + con.query(sql, values, function (err, result) { + if (err) + throw err; + if (result[0] && result[0].User_Name && result[0].User_Name == values[0]) { + res.status(200); + res.json(result[0]); + } + else { + res.status(400); + res.json({ "error": "you cannot access the api without being logged in" }); + } + }); +}); +router.get("/api/getotheruser", async function (req, res) { + res.set("Access-Control-Allow-Origin", "*"); + let username = req.query.user; + let sql = `select User_Name,User_Bio,User_Avatar,User_PublicKey from ipost.users where User_Name=?;`; + con.query(sql, [username], function (err, result) { + if (err) + throw err; + if (result[0] && result[0].User_Name && result[0].User_Name == username) { + res.json({ "username": username, "bio": result[0].User_Bio, "avatar": result[0].User_Avatar, "publicKey": result[0].User_PublicKey }); + } + else { + res.json({ "error": "there is no such user!" }); + } + }); +}); +router.get("/api/getPosts/*", async function (req, res) { + res.set("Access-Control-Allow-Origin", ""); + res.redirect("/api/getPosts"); +}); +router.get("/api/getPosts", async function (req, res) { + res.set("Access-Control-Allow-Origin", "*"); + if (req.query.channel != undefined) { + let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where post_receiver_name = ? group by post_id order by post_id desc limit 30;`; + con.query(sql, [encodeURIComponent(req.query.channel)], function (err, result) { + if (err) + throw err; + res.json(result); + }); } - }); -}) - - - - + else { //fallback + let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where (post_receiver_name is null or post_receiver_name = 'everyone') group by post_id order by post_id desc limit 30;`; + con.query(sql, [], function (err, result) { + if (err) + throw err; + res.json(result); + }); + } +}); +router.get("/api/getPostsLowerThan", async function (req, res) { + res.set("Access-Control-Allow-Origin", "*"); + if (req.query.channel != undefined) { + let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where ((post_receiver_name = ?) and (post_id < ?)) group by post_id order by post_id desc limit 30;`; + con.query(sql, [encodeURIComponent(req.query.channel), req.query.id], function (err, result) { + if (err) + throw err; + res.json(result); + }); + } + else { //fallback + let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where ((post_receiver_name is null or post_receiver_name = 'everyone') and (post_id < ?)) group by post_id order by post_id desc limit 30;`; + con.query(sql, [req.query.id], function (err, result) { + if (err) + throw err; + res.json(result); + }); + } +}); +router.get("/api/getPost", async function (req, res) { + res.set("Access-Control-Allow-Origin", "*"); + let arg = req.query.id; + let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id,post_receiver_name from ipost.posts where post_id=?;`; + con.query(sql, [arg], function (err, result) { + if (err) + throw err; + if (result[0]) { + res.set('Cache-Control', 'public, max-age=2592000'); //cache it for one month-ish + res.json(result[0]); + } + else { + res.json({ "error": "there is no such post!" }); + } + }); +}); +router.get("/api/getChannels", async function (req, res) { + res.set("Access-Control-Allow-Origin", "*"); + let sql = `select post_receiver_name from ipost.posts where post_is_private = '0' group by post_receiver_name;`; + con.query(sql, [], function (err, result) { + if (err) + throw err; + res.json(result); + }); +}); +router.post("/api/setBio", async function (req, res) { + res.set("Access-Control-Allow-Origin", ""); + let bio = req.body.Bio; + if (!bio) { + res.status(400); + res.json({ "error": "no bio set!" }); + return; + } + bio = encodeURIComponent(bio); + if (100 < bio.length) { + res.status(400); + res.json({ "error": "the bio is too long!" }); + return; + } + let sql = `update ipost.users set User_Bio=? where User_Name=?`; + con.query(sql, [bio, encodeURIComponent(res.locals.username)], function (err, result) { + if (err) + throw err; + res.json({ "success": "updated bio" }); + }); +}); +router.post("/api/changePW", async function (req, res) { + res.set("Access-Control-Allow-Origin", ""); + if ((typeof req.body.newPW) != "string") { + res.json({ "error": "incorrect password" }); + return; + } + if ((typeof req.body.currentPW) != "string") { + res.json({ "error": "incorrect password" }); + return; + } + if (req.body.newPW.length < 10) { + res.status(400); + res.json({ "error": "password is too short" }); + return; + } + let hashed_pw = SHA.SHA256(req.body.currentPW, res.locals.username, HASHES_DB); + let hashed_new_pw = SHA.SHA256(req.body.newPW, res.locals.username, HASHES_DB); + let sql = `select * from ipost.users where User_Name=? and User_PW=?;`; + let values = [res.locals.username, hashed_pw]; + con.query(sql, values, function (err, result) { + if (err) + throw err; + if (result[0] && result[0].User_Name && result[0].User_Name == res.locals.username) { + let sql = `update ipost.users set User_PW=? where User_Name=? and User_PW=?;`; + let values = [hashed_new_pw, res.locals.username, hashed_pw]; + con.query(sql, values, function (err, result) { + if (err) + throw err; + let ip = getIP(req); + let setTo = res.locals.username + " " + SHA.SHA256(req.body.newPW, res.locals.username, HASHES_COOKIE); + let cookiesigned = signature.sign(setTo, cookiesecret + ip); + res.cookie('AUTH_COOKIE', cookiesigned, { maxAge: Math.pow(10, 10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); + res.json({ "success": "successfully changed password" }); + }); + } + else { + res.json({ "error": "invalid password" }); + } + sent_res = true; + }); + setTimeout(function () { + if (!sent_res) + res.json({ "error": "timeout" }); + }, 3000); +}); +router.post("/api/changeUsername", async function (req, res) { + res.set("Access-Control-Allow-Origin", ""); + if ((typeof req.body.newUsername) != "string") { + res.status(400); + res.json({ "error": "incorrect username" }); + return; + } + if ((typeof req.body.currentPW) != "string") { + res.status(400); + res.json({ "error": "incorrect password" }); + return; + } + if (100 < req.body.newUsername.length) { + res.status(400); + res.json({ "error": "username is too long" }); + return; + } + if (req.body.newUsername == res.locals.username) { + res.status(400); + res.json({ "error": "username can't be the current one" }); + return; + } + let hashed_pw = SHA.SHA256(req.body.currentPW, res.locals.username, HASHES_DB); + let hashed_new_pw = SHA.SHA256(req.body.currentPW, req.body.newUsername, HASHES_DB); + let sql = `select * from ipost.users where User_Name=?;`; //check if pw is correct + let values = [res.locals.username]; + con.query(sql, values, function (err, result) { + if (err) + throw err; + if (result[0] && result[0].User_PW == hashed_pw) { + let sql = `select * from ipost.users where User_Name=?;`; //check if newUsername isn't already used + let values = [req.body.newUsername]; + con.query(sql, values, function (err, result) { + if (err) + throw err; + if (result[0]) { + res.json({ "error": "user with that username already exists" }); + return; + } + let sql = `update ipost.users set User_PW=?,User_Name=? where User_Name=? and User_PW=?;`; //change username in users + let values = [hashed_new_pw, req.body.newUsername, res.locals.username, hashed_pw]; + con.query(sql, values, function (err, result) { + if (err) + throw err; + let ip = getIP(req); + let setTo = req.body.newUsername + " " + SHA.SHA256(req.body.currentPW, req.body.newUsername, HASHES_COOKIE); + let cookiesigned = signature.sign(setTo, cookiesecret + ip); + res.cookie('AUTH_COOKIE', cookiesigned, { maxAge: Math.pow(10, 10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); + //updated username in the users table, but not yet on posts + let sql = `update ipost.posts set post_user_name=? where post_user_name=?;`; //change username of every past post sent + let values = [req.body.newUsername, res.locals.username, hashed_pw]; + con.query(sql, values, function (err, result) { + res.json({ "success": "successfully changed username" }); //done + }); + }); + }); + } + else { + res.json({ "error": "invalid password" }); + } + }); +}); /* END /API/* */ - - -router.get("/users/*", async function(req,res) { - if(!increaseUSERCall(req,res))return - res.sendFile(dir + "views/otheruser.html") -}) - +router.get("/users/*", async function (req, res) { + if (!increaseUSERCall(req, res)) + return; + res.sendFile(dir + "views/otheruser.html"); +}); router.get("/css/*", (request, response) => { - if(!increaseUSERCall(request,response))return - if(existsSync(__dirname + request.originalUrl)){ - response.sendFile(__dirname + request.originalUrl); - } else { - response.status(404).send("no file with that name found") - } - return; + if (!increaseUSERCall(request, response)) + return; + if (existsSync(__dirname + request.originalUrl)) { + response.sendFile(__dirname + request.originalUrl); + } + else { + response.status(404).send("no file with that name found"); + } + return; }); - router.get("/js/*", (request, response) => { - if(!increaseUSERCall(request,response))return - if(existsSync(__dirname + request.originalUrl)){ - response.sendFile(__dirname + request.originalUrl); - } else { - response.status(404).send("no file with that name found") - } - return; + if (!increaseUSERCall(request, response)) + return; + if (existsSync(__dirname + request.originalUrl)) { + response.sendFile(__dirname + request.originalUrl); + } + else { + response.status(404).send("no file with that name found"); + } + return; }); - router.get("/images/*", (request, response) => { - if(!increaseUSERCall(request,response))return - if(existsSync(__dirname + request.originalUrl)){ - response.sendFile(__dirname + request.originalUrl); - } else { - response.status(404).send("no file with that name found") - } - return; + if (!increaseUSERCall(request, response)) + return; + if (existsSync(__dirname + request.originalUrl)) { + response.sendFile(__dirname + request.originalUrl); + } + else { + response.status(404).send("no file with that name found"); + } + return; }); - router.get("/avatars/*", (request, response, next) => { - if(!increaseUSERCall(request,response))return - response.set('Cache-Control', 'public, max-age=2592000'); //cache it for one month-ish - let originalUrl = request.originalUrl.split("?").shift() - if(existsSync(dir + originalUrl + ".png")) { - return response.sendFile(dir + originalUrl + ".png"); - } - if(existsSync(dir + originalUrl)) { - return response.sendFile(dir + originalUrl); - } - response.status(404).send("No avatar with that name found") -}) - -router.get("/logout",async function(req,res) { - res.cookie("AUTH_COOKIE","", { maxAge: 0, httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }) - res.redirect("/") -}) - + if (!increaseUSERCall(request, response)) + return; + response.set('Cache-Control', 'public, max-age=2592000'); //cache it for one month-ish + let originalUrl = request.originalUrl.split("?").shift(); + if (existsSync(dir + originalUrl + ".png")) { + return response.sendFile(dir + originalUrl + ".png"); + } + if (existsSync(dir + originalUrl)) { + return response.sendFile(dir + originalUrl); + } + response.status(404).send("No avatar with that name found"); +}); +router.get("/logout", async function (req, res) { + res.cookie("AUTH_COOKIE", "", { maxAge: 0, httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); + res.redirect("/"); +}); router.get("/*", (request, response, next) => { - if(!increaseUSERCall(request,response))return - let originalUrl = request.originalUrl.split("?").shift() - if(existsSync(dir + "views/"+originalUrl+".html")) { - return response.sendFile(dir + "views/"+originalUrl+".html"); - } - if(existsSync(dir + "views"+originalUrl)) { - return response.sendFile(dir + "views"+originalUrl); - } - if(existsSync(dir + "views"+originalUrl+".html")) { - return response.sendFile(dir + "views"+originalUrl+".html"); - } - if(existsSync(dir + "views"+originalUrl)) { - return response.sendFile(dir + "views"+originalUrl); - } - response.status(404).send("No file with that name found") -}) - -router.post("/register",async function(req,res) { - for (let i = 0; i < 10; i++) { //don't want people spam registering - if(!increaseAPICall(req,res))return; - } - res.status(200) - - if((typeof req.body.user) != "string") { - res.json({"error":"incorrect username"}) - return - } - if((typeof req.body.pass) != "string") { - res.json({"error":"incorrect password"}) - return - } - - let username = req.body.user.toString() - username = username.replace(/\s/gi,"") - let password = req.body.pass.toString() - if(!username) { - res.status(400) - res.redirect("/register?success=false&reason=username") - return - } - if(username=="") { - res.status(400) - res.redirect("/register?success=false&reason=username") - return - } - if(password.length < 10) { - res.status(400) - res.send("password is too short") - return - } - if(username.length > 25) { - res.status(400) - res.send("username is too long") - return - } - if(username.search("@")!=-1) { - res.status(400) - res.send("username can't contain @-characters") - return - } - if(!password) { - res.status(400) - res.redirect("/register?success=false&reason=password") - return - } - let userexistssql = `SELECT User_Name from ipost.users where User_Name = ?` - con.query(userexistssql,[encodeURIComponent(username)],function(error,result) { - if(result && result[0] && result[0].User_Name) { - res.status(400) - res.redirect("/register?success=false&reason=already_exists") - return + if (!increaseUSERCall(request, response)) + return; + let originalUrl = request.originalUrl.split("?").shift(); + if (existsSync(dir + "views/" + originalUrl + ".html")) { + return response.sendFile(dir + "views/" + originalUrl + ".html"); } - let less_hashed_pw = SHA.SHA256(password,username,HASHES_DIFF) - let hashed_pw = SHA.SHA256(less_hashed_pw,username,HASHES_COOKIE) - let ip = getIP(req) - let setTo = username + " " + SHA.SHA256(password,username,HASHES_COOKIE) - let cookiesigned = signature.sign(setTo, cookiesecret+ip); - ip = SHA.SHA256(ip,setTo,HASHES_DB) - - const default_settings = {} - - let values = [encodeURIComponent(username),hashed_pw, Date.now(), ip, ip,JSON.stringify(default_settings)] - let sql = `INSERT INTO ipost.users (User_Name, User_PW, User_CreationStamp, User_CreationIP, User_LastIP, User_Settings) VALUES (?, ?, ?, ?, ?, ?, ?, ?);` - con.query(sql, values, function (err, result) { - if (err) throw err; - res.cookie('AUTH_COOKIE',cookiesigned, { maxAge: Math.pow(10,10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - res.redirect("/user?success=true") + if (existsSync(dir + "views" + originalUrl)) { + return response.sendFile(dir + "views" + originalUrl); + } + if (existsSync(dir + "views" + originalUrl + ".html")) { + return response.sendFile(dir + "views" + originalUrl + ".html"); + } + if (existsSync(dir + "views" + originalUrl)) { + return response.sendFile(dir + "views" + originalUrl); + } + response.status(404).send("No file with that name found"); +}); +router.post("/register", async function (req, res) { + for (let i = 0; i < 10; i++) { //don't want people spam registering + if (!increaseAPICall(req, res)) + return; + } + res.status(200); + if ((typeof req.body.user) != "string") { + res.json({ "error": "incorrect username" }); + return; + } + if ((typeof req.body.pass) != "string") { + res.json({ "error": "incorrect password" }); + return; + } + let username = req.body.user.toString(); + username = username.replace(/\s/gi, ""); + let password = req.body.pass.toString(); + if (!username) { + res.status(400); + res.redirect("/register?success=false&reason=username"); + return; + } + if (username == "") { + res.status(400); + res.redirect("/register?success=false&reason=username"); + return; + } + if (password.length < 10) { + res.status(400); + res.send("password is too short"); + return; + } + if (username.length > 25) { + res.status(400); + res.send("username is too long"); + return; + } + if (username.search("@") != -1) { + res.status(400); + res.send("username can't contain @-characters"); + return; + } + if (!password) { + res.status(400); + res.redirect("/register?success=false&reason=password"); + return; + } + let userexistssql = `SELECT User_Name from ipost.users where User_Name = ?`; + con.query(userexistssql, [encodeURIComponent(username)], function (error, result) { + if (result && result[0] && result[0].User_Name) { + res.status(400); + res.redirect("/register?success=false&reason=already_exists"); + return; + } + let less_hashed_pw = SHA.SHA256(password, username, HASHES_DIFF); + let hashed_pw = SHA.SHA256(less_hashed_pw, username, HASHES_COOKIE); + let ip = getIP(req); + let setTo = username + " " + SHA.SHA256(password, username, HASHES_COOKIE); + let cookiesigned = signature.sign(setTo, cookiesecret + ip); + ip = SHA.SHA256(ip, setTo, HASHES_DB); + const default_settings = {}; + let values = [encodeURIComponent(username), hashed_pw, Date.now(), ip, ip, JSON.stringify(default_settings)]; + let sql = `INSERT INTO ipost.users (User_Name, User_PW, User_CreationStamp, User_CreationIP, User_LastIP, User_Settings) VALUES (?, ?, ?, ?, ?, ?, ?, ?);`; + con.query(sql, values, function (err, result) { + if (err) + throw err; + res.cookie('AUTH_COOKIE', cookiesigned, { maxAge: Math.pow(10, 10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); + res.redirect("/user?success=true"); + }); }); - }) -}) - -router.post("/login",async function(req,res) { - if(!increaseAPICall(req,res))return; - if(!increaseAPICall(req,res))return; - //login is counted twice (think of bruteforces man) - if((typeof req.body.user) != "string") { - res.json({"error":"incorrect username"}) - return - } - if((typeof req.body.pass) != "string") { - res.json({"error":"incorrect password"}) - return - } - if(!req.body.user){ - res.status(400) - res.send("no username given") - return - } - if(!req.body.pass){ - res.status(400) - res.send("no password given") - return - } - let username = req.body.user.toString() - username = username.replace(" ","") - let password = req.body.pass.toString() - if(!username) { - res.status(400) - res.send("no username given") - return - } - if(username.length > 25) { - res.status(400) - res.send("username is too long") - return - } - if(password.length < 10) { - res.status(400) - res.send("password is too short") - return - } - if(!password) { - res.status(400) - res.send("no password given") - return - } - let less_hashed_pw = SHA.SHA256(password,username,HASHES_DIFF) - let hashed_pw = SHA.SHA256(less_hashed_pw,username,HASHES_COOKIE) - - let userexistssql = `SELECT * from ipost.users where User_Name = ? and User_PW = ?;` - con.query(userexistssql,[encodeURIComponent(username),hashed_pw],function(error,result) { - if(result && result[0]) { - let ip = getIP(req) - let setTo = username + " " + SHA.SHA256(password,username,HASHES_COOKIE) - let cookiesigned = signature.sign(setTo, cookiesecret+ip); - res.cookie('AUTH_COOKIE',cookiesigned, { maxAge: Math.pow(10,10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - - ip = SHA.SHA256(ip,setTo,HASHES_DB) - if(result[0].User_LastIP != ip) { - let sql = `update ipost.users set User_LastIP = ? where User_Name = ?;` - con.query(sql,[ip,encodeURIComponent(username)],function(error,result) { - if(error)throw error - }) - } - res.redirect("/user?success=true") - } else { - res.redirect("/login?success=false?reason=noUser") +}); +router.post("/login", async function (req, res) { + if (!increaseAPICall(req, res)) + return; + if (!increaseAPICall(req, res)) + return; + //login is counted twice (think of bruteforces man) + if ((typeof req.body.user) != "string") { + res.json({ "error": "incorrect username" }); + return; } - }); -}) - -console.log(5,"finished loading routes") - -app.use(router) - + if ((typeof req.body.pass) != "string") { + res.json({ "error": "incorrect password" }); + return; + } + if (!req.body.user) { + res.status(400); + res.send("no username given"); + return; + } + if (!req.body.pass) { + res.status(400); + res.send("no password given"); + return; + } + let username = req.body.user.toString(); + username = username.replace(" ", ""); + let password = req.body.pass.toString(); + if (!username) { + res.status(400); + res.send("no username given"); + return; + } + if (username.length > 25) { + res.status(400); + res.send("username is too long"); + return; + } + if (password.length < 10) { + res.status(400); + res.send("password is too short"); + return; + } + if (!password) { + res.status(400); + res.send("no password given"); + return; + } + let less_hashed_pw = SHA.SHA256(password, username, HASHES_DIFF); + let hashed_pw = SHA.SHA256(less_hashed_pw, username, HASHES_COOKIE); + let userexistssql = `SELECT * from ipost.users where User_Name = ? and User_PW = ?;`; + con.query(userexistssql, [encodeURIComponent(username), hashed_pw], function (error, result) { + if (result && result[0]) { + let ip = getIP(req); + let setTo = username + " " + SHA.SHA256(password, username, HASHES_COOKIE); + let cookiesigned = signature.sign(setTo, cookiesecret + ip); + res.cookie('AUTH_COOKIE', cookiesigned, { maxAge: Math.pow(10, 10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); + ip = SHA.SHA256(ip, setTo, HASHES_DB); + if (result[0].User_LastIP != ip) { + let sql = `update ipost.users set User_LastIP = ? where User_Name = ?;`; + con.query(sql, [ip, encodeURIComponent(username)], function (error, result) { + if (error) + throw error; + }); + } + res.redirect("/user?success=true"); + } + else { + res.redirect("/login?success=false?reason=noUser"); + } + }); +}); +console.log(5, "finished loading routes"); +app.use(router); const httpServer = http.createServer(app); -httpServer.listen(config["ports"]["http"],function(){ - console.log(5,"HTTP Server is listening") +httpServer.listen(config["ports"]["http"], function () { + console.log(5, "HTTP Server is listening"); }); - -const privateKey = readFileSync(config["ssl"]["privateKey"]).toString() -const certificate = readFileSync(config["ssl"]["certificate"]).toString() - -const credentials = {key: privateKey, cert: certificate}; - -var httpsServer -if(DID_I_FINALLY_ADD_HTTPS) { - httpsServer = https.createServer(credentials, app); - httpsServer.listen(config["ports"]["https"],function(){ - console.log(5,"HTTPS Server is listening") - }); -} else { - httpsServer = httpServer +const privateKey = readFileSync(config["ssl"]["privateKey"]).toString(); +const certificate = readFileSync(config["ssl"]["certificate"]).toString(); +const credentials = { key: privateKey, cert: certificate }; +var httpsServer; +if (DID_I_FINALLY_ADD_HTTPS) { + httpsServer = https.createServer(credentials, app); + httpsServer.listen(config["ports"]["https"], function () { + console.log(5, "HTTPS Server is listening"); + }); +} +else { + httpsServer = httpServer; } - - wss = new WebSocket({ - server: httpsServer, - perMessageDeflate: { - zlibDeflateOptions: { - chunkSize: 1024, - memLevel: 7, - level: 3 - }, - zlibInflateOptions: { - chunkSize: 10 * 1024 - }, - clientNoContextTakeover: true, - serverNoContextTakeover: true, - serverMaxWindowBits: 10, - concurrencyLimit: 10, - threshold: 1024 * 16 - } -}); - -wss.on("connection", function connection(ws) { - ws.channel = "everyone" - ws.on("message", function incoming(message) { - message = JSON.parse(message) - if(message.id == "switchChannel") { - ws.channel = decodeURIComponent(message.data) + server: httpsServer, + perMessageDeflate: { + zlibDeflateOptions: { + chunkSize: 1024, + memLevel: 7, + level: 3 + }, + zlibInflateOptions: { + chunkSize: 10 * 1024 + }, + clientNoContextTakeover: true, + serverNoContextTakeover: true, + serverMaxWindowBits: 10, + concurrencyLimit: 10, + threshold: 1024 * 16 } - }) -}) - -commonfunctions.wss = wss - -console.log(5,"starting up all services") +}); +wss.on("connection", function connection(ws) { + ws.channel = "everyone"; + ws.on("message", function incoming(message) { + message = JSON.parse(message); + if (message.id == "switchChannel") { + ws.channel = decodeURIComponent(message.data); + } + }); +}); +commonfunctions.wss = wss; +console.log(5, "starting up all services"); diff --git a/server_esm.js b/server_esm.js deleted file mode 100644 index 0b43a47..0000000 --- a/server_esm.js +++ /dev/null @@ -1,1036 +0,0 @@ -import http from "http"; -import https from "https"; -import * as express from "express"; -import useragent from "express-useragent"; -import fileUpload from "express-fileupload"; -import * as bodyParser from "body-parser"; -import cookieParser from "cookie-parser"; -import * as signature from "cookie-signature"; -import * as mysql from "mysql"; -import * as ws from "ws"; -import Jimp from "jimp"; -import SHA from "./extra_modules/SHA.js"; -import getIP from "./extra_modules/getip.js"; -import unsign from "./extra_modules/unsign.js"; -import { readFileSync, mkdir, existsSync, appendFile } from "fs"; -import { format } from "util"; -import { setup as optionssetup } from "./routes/api/options.js"; -import { setup as allsetup } from "./routes/api/all.js"; -import { setup as settingshandlersetup } from "./routes/api/settingshandler.js"; -import { setup as postsetup } from "./routes/api/post.js"; -import { setup as dmsPersonalMessagessetup } from "./routes/api/dms/PersonalMessages.js"; -import { setup as dmspostsetup } from "./routes/api/dms/post.js"; - -import { fileURLToPath } from 'url' -import { dirname } from 'path' -const __filename = fileURLToPath(import.meta.url) -const __dirname = dirname(__filename) - - -/** - * makes sure that a given folder exists, if it doesn't it creates one for you - * @param {string} path the path of the folder - * @param {permission} mask permission mask for the new folder to have - * @param {Function} cb callback, gives null if the folder exists, otherwise gives the error - * @return {undefined} see: callback - */ -function ensureExists(path, mask, cb) { - if (typeof mask == 'function') { // Allow the `mask` parameter to be optional - cb = mask; - mask = 0o744; - } - mkdir(path, mask, function (err) { - if (err) { - if (err.code == 'EEXIST') - cb(null); // Ignore the error if the folder already exists - else - cb(err); // Something else went wrong - } - else - cb(null); // Successfully created folder - }); -} -const config = JSON.parse(readFileSync("server_config.json")); -const time = Date.now(); -const original_log = console.log; -/** - * custom logging function - * @param {number} level importance level if information - * @param {any} info information to format + log - * @return {undefined} returns nothing - */ -function log_info(level, ...info) { - let text = info; - if (text == undefined || text.length == 0) { - text = level; - level = 5; - } - if (config["logs"] && config["logs"]["level"] && config["logs"]["level"] >= level) { - let tolog = `[INFO] [${Date.now()}] : ${format(text)} \n`; - original_log(tolog); //still has some nicer colors - ensureExists(__dirname + '/logs/', function (err) { - if (err) { - process.stderr.write(tolog); //just write it to stderr - } - else { - appendFile(__dirname + "/logs/" + time, tolog, function (err) { - if (err) { - process.stderr.write(err); - } - }); - } - }); - } -} -console.log = log_info; - -const WebSocket = ws.WebSocketServer; - -import {EventEmitter} from 'events'; -import merge from 'merge-descriptors'; - -/** - * Create an express application. - * - * @return {Function} - * @api public - */ - - function createApplication() { - var app = function(req, res, next) { - app.handle(req, res, next); - }; - - merge(app, EventEmitter.prototype, false); - merge(app, express.application, false); - - // expose the prototype that will get set on requests - app.request = Object.create(express.request, { - app: { configurable: true, enumerable: true, writable: true, value: app } - }) - - // expose the prototype that will get set on responses - app.response = Object.create(express.response, { - app: { configurable: true, enumerable: true, writable: true, value: app } - }) - - app.init(); - return app; -} - -const router = express.Router(); -const app = createApplication(); -const HASHES_DB = config.cookies.server_hashes; -const HASHES_COOKIE = config.cookies.client_hashes; -const HASHES_DIFF = HASHES_DB - HASHES_COOKIE; -const DID_I_FINALLY_ADD_HTTPS = true; -const con = mysql.createPool({ - connectionLimit: config.mysql.connections, - host: config.mysql.host, - user: config.mysql.user, - password: readFileSync(config.mysql.password_file).toString() -}); -const dir = __dirname + "/"; -const cookiesecret = readFileSync("cookiesecret.txt").toString(); -/** - * quick function to convert data to base64 - * @param {any} data data to encode in base64 - * @return {string} base64 encoded data - */ -function b64(data) { - let buff = Buffer.from(data); - return buff.toString('base64'); -} -/** - * custom, bad random number generator - * @param {number} seed seed for the number generator, defaults to current timestamp - * @constructor - */ -function RNG(seed) { - if (!seed) - seed = Date.now(); - this.seed = seed; - this.random = function (min, max) { - if (!min) - min = 0; - if (!max) { - max = min; - min = 0; - } - this.seed += Math.log(Math.abs(Math.sin(this.seed)) * 100); - return Math.abs(Math.sin(this.seed)) * max + min; - }; - this.rand = function (min, max) { - return Math.floor(this.random(min, max)); - }; -} -/** - * waits x ms - * @param {number} ms amount of ms to sleep for - * @return {promise} promise that gets resolved after x ms - */ -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} -const rand = new RNG(); -const genstring_characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; -const genstring_charactersLength = genstring_characters.length; -/** - * generates a semi-random string - * @param {number} length length of string to generate - * @return {string} semi-random string generated - */ -function genstring(length) { - let result = ""; - for (let i = 0; i < length; i++) { - result += genstring_characters.charAt(rand.rand(genstring_charactersLength)); - } - return result; -} -/** - * handles client errors, used by expressJS - */ -function clientErrorHandler(err, req, res, next) { - if (err) { - if (req.xhr) { - res.status(200).send({ error: 'Something failed!' }); - } - else { - console.log(1, err); - } - } - else { - next(); - } -} -/** - * utility function to get a key by its value in an object - * @param {object} object object to get key from - * @param {any} value value to get key from - * @return {any} key to the given value inside the object - */ -function getKeyByValue(object, value) { - return Object.keys(object).find(key => object[key] === value); -} -var API_CALLS = {}; -var API_CALLS_ACCOUNT = {}; -var USER_CALLS = {}; -var SESSIONS = {}; -var REVERSE_SESSIONS = {}; -var INDIVIDUAL_CALLS = {}; -/** - * clears current api call list (per IP) - * @return {undefined} returns nothing - */ -function clear_api_calls() { - API_CALLS = {}; -} -/** - * clears current api account call list (per account) - * @return {undefined} returns nothing - */ -function clear_account_api_calls() { - API_CALLS_ACCOUNT = {}; -} -/** - * clears current user file call list (per IP) - * @return {undefined} returns nothing - */ -function clear_user_calls() { - USER_CALLS = {}; -} -setInterval(clear_api_calls, config.rate_limits.api.reset_time); -setInterval(clear_account_api_calls, config.rate_limits.api.reset_time); -setInterval(clear_user_calls, config.rate_limits.user.reset_time); -function increaseIndividualCall(url, req) { - let conf = config["rate_limits"]["individual"][url]; - if (!conf) { - console.log(5, "uri not in individual ratelimiter", url); - return true; - } - if (!conf["enabled"]) - return true; - let ip = getIP(req); - if (INDIVIDUAL_CALLS[ip] == undefined) - INDIVIDUAL_CALLS[ip] = {}; - if (INDIVIDUAL_CALLS[ip][url] == undefined) - INDIVIDUAL_CALLS[ip][url] = 0; - if (INDIVIDUAL_CALLS[ip][url] == 0) { - setTimeout(function () { - INDIVIDUAL_CALLS[ip][url] = 0; - }, conf["reset_time"]); - } - INDIVIDUAL_CALLS[ip][url]++; - if (INDIVIDUAL_CALLS[ip][url] >= conf["max"]) { - console.log(5, "ratelimiting someone on", url, INDIVIDUAL_CALLS[ip][url], conf["max"]); - return false; - } - return true; -} -function increaseAccountAPICall(req, res) { - let cookie = req.cookies.AUTH_COOKIE; - if (!cookie) { - return true; - } - let unsigned = unsign.unsign(cookie, req, res); - if (!unsigned) { - return true; //if there's no account, why not just ignore it - } - unsigned = decodeURIComponent(unsigned); - if (!unsigned) - return false; - let values = unsigned.split(" "); - let username = values[0]; - if (API_CALLS_ACCOUNT[username] == undefined) - API_CALLS_ACCOUNT[username] = 0; - if (API_CALLS_ACCOUNT[username] >= config.rate_limits.api.max_per_account) { - res.status(429); - res.send("You are sending way too many api calls!"); - return false; - } - return true; -} -function increaseAPICall(req, res, next) { - let ip = getIP(req); - if (API_CALLS[ip] == undefined) - API_CALLS[ip] = 0; - if (API_CALLS[ip] >= config.rate_limits.api.max_without_session) { - if (REVERSE_SESSIONS[ip] && req.cookies.session !== REVERSE_SESSIONS[ip]) { //expected a session, but didn't get one - res.status(429); - res.send("You are sending way too many api calls!"); - return; - } - if (!req.cookies.session) { - let session; - do { - session = genstring(300); - } while (SESSIONS[session] != undefined); - SESSIONS[session] = ip; - REVERSE_SESSIONS[ip] = session; - setTimeout(function () { - SESSIONS[session] = undefined; - REVERSE_SESSIONS[ip] = undefined; - }, 50000); - res.cookie('session', session, { maxAge: 100000, httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - console.log(3, "sending session to " + ip); - } - } - if (API_CALLS[ip] >= config.rate_limits.api.max_with_session) { - res.status(429); - res.send("You are sending too many api calls!"); - console.log(3, "rate limiting " + ip); - return false; - } - API_CALLS[ip]++; - if (!increaseAccountAPICall(req, res)) - return false; //can't forget account-based ratelimits - if (next) - next(); - return true; -} -function increaseUSERCall(req, res, next) { - let ip = getIP(req); - if (USER_CALLS[ip] == undefined) - USER_CALLS[ip] = 0; - if (USER_CALLS[ip] >= config.rate_limits.user.max) { - res.status(429); - res.send("You are sending too many requests!"); - console.log(2, "rate limiting " + ip); - return false; - } - USER_CALLS[ip]++; - if (next) - next(); - return true; -} -console.log(5, "loading routes"); -app.use(useragent.express()); -app.use(fileUpload()); - -app.use(bodyParser.default.json({ limit: "100mb" })); -app.use(bodyParser.default.urlencoded({ limit: "100mb", extended: true })); -app.use(clientErrorHandler); -app.use(cookieParser(cookiesecret)); -var blocked_headers = [ - 'HTTP_VIA', - 'HTTP_X_FORWARDED_FOR', - 'HTTP_FORWARDED_FOR', - 'HTTP_X_FORWARDED', - 'HTTP_FORWARDED', - 'HTTP_CLIENT_IP', - 'HTTP_FORWARDED_FOR_IP', - 'VIA', - 'X_FORWARDED_FOR', - 'FORWARDED_FOR', - 'X_FORWARDED', - 'FORWARDED', - 'CLIENT_IP', - 'FORWARDED_FOR_IP', - 'HTTP_PROXY_CONNECTION' -]; -if (!config.disallow_proxies_by_headers) { - blocked_headers = []; -} -app.use(function (req, res, next) { - res.set("X-XSS-Protection", "1; mode=block"); - next(); -}); -if (DID_I_FINALLY_ADD_HTTPS) { - //auto redirect to https - app.use((req, res, next) => { - if (req.secure) { - //already secure - next(); - } - else { - //redirect to https - res.redirect('https://' + req.headers.host + req.url); - } - }); -} -app.use("/*", function (req, res, next) { - res.set("x-powered-by", "ipost"); - for (let i = 0; i < blocked_headers.length; i++) { - if (req.header(blocked_headers[i]) != undefined) { - res.json({ "error": "we don't allow proxies on our website." }); - return; - } - } - let fullurl = req.baseUrl + req.path; - if (fullurl != "/") { - fullurl = fullurl.substring(0, fullurl.length - 1); - } - if (!increaseIndividualCall(fullurl, req)) { - res.status(429); - res.json({ "error": "you are sending too many requests!" }); - return; - } - next(); -}); -router.get("/", function (req, res) { - if (!increaseUSERCall(req, res)) - return; - res.sendFile(dir + "views/index.html"); -}); -console.log(5, "finished loading user routes, starting with api routes"); -/* - -START /API/* - -*/ -var wss; -var commonfunctions = { - increaseAPICall, - increaseUSERCall, - increaseAccountAPICall, - increaseIndividualCall, - wss, - genstring -}; -optionssetup(router, con, commonfunctions); -allsetup(router, con, commonfunctions); -settingshandlersetup(router, con, commonfunctions); -postsetup(router, con, commonfunctions); -dmsPersonalMessagessetup(router, con, commonfunctions); -dmspostsetup(router, con, commonfunctions); -// const toLoad = [ -// "api/options.js", -// "api/all.js", -// "api/settingshandler.js", -// "api/post.js", -// "api/dms/PersonalMessages.js", -// "api/dms/post.js", -// ] -// for (let i = 0; i < toLoad.length; i++) { -// require("./routes/"+toLoad[i]).setup(router,con,commonfunctions) -// } -// let options = require("./routes/api/options.js") -// options.setup(router,con,commonfunctions) -// let apiALL = require("./routes/api/all.js") -// apiALL.setup(router,con,commonfunctions) -// let settingshandler = require("./routes/api/settingshandler.js") -// settingshandler.setup(router,con,commonfunctions) -router.get("/api/search", async function (req, res) { - res.set("Access-Control-Allow-Origin", ""); - let type = req.query.type; - let arg = encodeURIComponent(req.query.selector); - if (type == "user") { - let sql = `select User_Name,User_Bio,User_Avatar from ipost.users where User_Name like ? limit 10;`; - con.query(sql, [`%${arg}%`], function (err, result) { - if (err) - throw err; - if (result[0] && result[0].User_Name) { - res.json(result); - } - else { - res.json({ "error": "there is no such user!" }); - } - }); - } - else if (type == "post") { - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id from ipost.posts where post_text like ? and (post_receiver_name is null or post_receiver_name = 'everyone') order by post_id desc limit 20;`; - con.query(sql, [`%${arg}%`], function (err, result) { - if (err) - throw err; - if (result[0]) { - res.json(result); - } - else { - res.json({ "error": "there is no such post!" }); - } - }); - } - else { - res.json({ "error": "invalid type passed along, expected `user` or `post`" }); - } -}); -router.post("/api/setavatar", function (req, res) { - res.set("Access-Control-Allow-Origin", ""); - if (!req.files || Object.keys(req.files).length === 0) { - return res.status(400).send('No files were uploaded. (req.files)'); - } - let avatar = req.files.avatar; - if (!avatar) { - return res.status(400).send('No files were uploaded. (req.files.)'); - } - let DOSbuf = Buffer.from('ffd8ffc1f151d800ff51d800ffdaffde', 'hex'); //causes DOS - if (avatar.data.includes(DOSbuf)) { - console.log(3, "DOS image was caught"); - return res.status(400).send('No files were uploaded. (req.files.)'); - } - //DOS introduced through jimp (uses jpeg-js) - const avatars = __dirname + '/avatars/'; - ensureExists(avatars, function (err) { - if (err) { - return res.status(500).json({ "error": "there's been an internal server error." }); - } - if (res.locals.avatar) { - unlinkSync(avatars + res.locals.avatar); - } - let filename = genstring(96) + ".png"; - while (existsSync(avatars + "/" + filename) || filename == ".png") { - console.log(5, "already have file: ", filename); - original_log("already have file: ", filename); - filename = genstring(96) + ".png"; - } - avatar.mv(avatars + "temp_" + filename, function (err) { - if (err) { - return res.status(500).json({ "error": "there's been an internal server error." }); - } - Jimp.read(avatars + "temp_" + filename).then(function (image) { - image.resize(100, 100); - image.write(avatars + filename); - let sql = `update ipost.users set User_Avatar=? where User_Name=?`; - con.query(sql, [filename, encodeURIComponent(res.locals.username)], function (err, result) { - if (err) - throw err; - res.json({ "success": "updated avatar" }); - unlinkSync(avatars + "temp_" + filename); - }); - }); - }); - }); -}); -router.get("/api/getuser", async function (req, res) { - res.json({ "username": res.locals.username, "bio": res.locals.bio, "avatar": res.locals.avatar }); -}); -router.get("/api/getalluserinformation", async function (req, res) { - res.set("Access-Control-Allow-Origin", ""); //we don't want that here - let unsigned = unsign.getunsigned(req, res); - if (!unsigned) - return; - unsigned = decodeURIComponent(unsigned); - let sql = `select * from ipost.users where User_Name=? and User_PW=?;`; - let values = unsigned.split(" "); - values[1] = SHA.SHA256(values[1], values[0], HASHES_DIFF); - con.query(sql, values, function (err, result) { - if (err) - throw err; - if (result[0] && result[0].User_Name && result[0].User_Name == values[0]) { - res.status(200); - res.json(result[0]); - } - else { - res.status(400); - res.json({ "error": "you cannot access the api without being logged in" }); - } - }); -}); -router.get("/api/getotheruser", async function (req, res) { - res.set("Access-Control-Allow-Origin", "*"); - let username = req.query.user; - let sql = `select User_Name,User_Bio,User_Avatar,User_PublicKey from ipost.users where User_Name=?;`; - con.query(sql, [username], function (err, result) { - if (err) - throw err; - if (result[0] && result[0].User_Name && result[0].User_Name == username) { - res.json({ "username": username, "bio": result[0].User_Bio, "avatar": result[0].User_Avatar, "publicKey": result[0].User_PublicKey }); - } - else { - res.json({ "error": "there is no such user!" }); - } - }); -}); -router.get("/api/getPosts/*", async function (req, res) { - res.set("Access-Control-Allow-Origin", ""); - res.redirect("/api/getPosts"); -}); -router.get("/api/getPosts", async function (req, res) { - res.set("Access-Control-Allow-Origin", "*"); - if (req.query.channel != undefined) { - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where post_receiver_name = ? group by post_id order by post_id desc limit 30;`; - con.query(sql, [encodeURIComponent(req.query.channel)], function (err, result) { - if (err) - throw err; - res.json(result); - }); - } - else { //fallback - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where (post_receiver_name is null or post_receiver_name = 'everyone') group by post_id order by post_id desc limit 30;`; - con.query(sql, [], function (err, result) { - if (err) - throw err; - res.json(result); - }); - } -}); -router.get("/api/getPostsLowerThan", async function (req, res) { - res.set("Access-Control-Allow-Origin", "*"); - if (req.query.channel != undefined) { - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where ((post_receiver_name = ?) and (post_id < ?)) group by post_id order by post_id desc limit 30;`; - con.query(sql, [encodeURIComponent(req.query.channel), req.query.id], function (err, result) { - if (err) - throw err; - res.json(result); - }); - } - else { //fallback - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id from ipost.posts where ((post_receiver_name is null or post_receiver_name = 'everyone') and (post_id < ?)) group by post_id order by post_id desc limit 30;`; - con.query(sql, [req.query.id], function (err, result) { - if (err) - throw err; - res.json(result); - }); - } -}); -router.get("/api/getPost", async function (req, res) { - res.set("Access-Control-Allow-Origin", "*"); - let arg = req.query.id; - let sql = `select post_user_name,post_text,post_time,post_special_text,post_id,post_from_bot,post_reply_id,post_receiver_name from ipost.posts where post_id=?;`; - con.query(sql, [arg], function (err, result) { - if (err) - throw err; - if (result[0]) { - res.set('Cache-Control', 'public, max-age=2592000'); //cache it for one month-ish - res.json(result[0]); - } - else { - res.json({ "error": "there is no such post!" }); - } - }); -}); -router.get("/api/getChannels", async function (req, res) { - res.set("Access-Control-Allow-Origin", "*"); - let sql = `select post_receiver_name from ipost.posts where post_is_private = '0' group by post_receiver_name;`; - con.query(sql, [], function (err, result) { - if (err) - throw err; - res.json(result); - }); -}); -router.post("/api/setBio", async function (req, res) { - res.set("Access-Control-Allow-Origin", ""); - let bio = req.body.Bio; - if (!bio) { - res.status(400); - res.json({ "error": "no bio set!" }); - return; - } - bio = encodeURIComponent(bio); - if (100 < bio.length) { - res.status(400); - res.json({ "error": "the bio is too long!" }); - return; - } - let sql = `update ipost.users set User_Bio=? where User_Name=?`; - con.query(sql, [bio, encodeURIComponent(res.locals.username)], function (err, result) { - if (err) - throw err; - res.json({ "success": "updated bio" }); - }); -}); -router.post("/api/changePW", async function (req, res) { - res.set("Access-Control-Allow-Origin", ""); - if ((typeof req.body.newPW) != "string") { - res.json({ "error": "incorrect password" }); - return; - } - if ((typeof req.body.currentPW) != "string") { - res.json({ "error": "incorrect password" }); - return; - } - if (req.body.newPW.length < 10) { - res.status(400); - res.json({ "error": "password is too short" }); - return; - } - let hashed_pw = SHA.SHA256(req.body.currentPW, res.locals.username, HASHES_DB); - let hashed_new_pw = SHA.SHA256(req.body.newPW, res.locals.username, HASHES_DB); - let sql = `select * from ipost.users where User_Name=? and User_PW=?;`; - let values = [res.locals.username, hashed_pw]; - con.query(sql, values, function (err, result) { - if (err) - throw err; - if (result[0] && result[0].User_Name && result[0].User_Name == res.locals.username) { - let sql = `update ipost.users set User_PW=? where User_Name=? and User_PW=?;`; - let values = [hashed_new_pw, res.locals.username, hashed_pw]; - con.query(sql, values, function (err, result) { - if (err) - throw err; - let ip = getIP(req); - let setTo = res.locals.username + " " + SHA.SHA256(req.body.newPW, res.locals.username, HASHES_COOKIE); - let cookiesigned = signature.sign(setTo, cookiesecret + ip); - res.cookie('AUTH_COOKIE', cookiesigned, { maxAge: Math.pow(10, 10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - res.json({ "success": "successfully changed password" }); - }); - } - else { - res.json({ "error": "invalid password" }); - } - sent_res = true; - }); - setTimeout(function () { - if (!sent_res) - res.json({ "error": "timeout" }); - }, 3000); -}); -router.post("/api/changeUsername", async function (req, res) { - res.set("Access-Control-Allow-Origin", ""); - if ((typeof req.body.newUsername) != "string") { - res.status(400); - res.json({ "error": "incorrect username" }); - return; - } - if ((typeof req.body.currentPW) != "string") { - res.status(400); - res.json({ "error": "incorrect password" }); - return; - } - if (100 < req.body.newUsername.length) { - res.status(400); - res.json({ "error": "username is too long" }); - return; - } - if (req.body.newUsername == res.locals.username) { - res.status(400); - res.json({ "error": "username can't be the current one" }); - return; - } - let hashed_pw = SHA.SHA256(req.body.currentPW, res.locals.username, HASHES_DB); - let hashed_new_pw = SHA.SHA256(req.body.currentPW, req.body.newUsername, HASHES_DB); - let sql = `select * from ipost.users where User_Name=?;`; //check if pw is correct - let values = [res.locals.username]; - con.query(sql, values, function (err, result) { - if (err) - throw err; - if (result[0] && result[0].User_PW == hashed_pw) { - let sql = `select * from ipost.users where User_Name=?;`; //check if newUsername isn't already used - let values = [req.body.newUsername]; - con.query(sql, values, function (err, result) { - if (err) - throw err; - if (result[0]) { - res.json({ "error": "user with that username already exists" }); - return; - } - let sql = `update ipost.users set User_PW=?,User_Name=? where User_Name=? and User_PW=?;`; //change username in users - let values = [hashed_new_pw, req.body.newUsername, res.locals.username, hashed_pw]; - con.query(sql, values, function (err, result) { - if (err) - throw err; - let ip = getIP(req); - let setTo = req.body.newUsername + " " + SHA.SHA256(req.body.currentPW, req.body.newUsername, HASHES_COOKIE); - let cookiesigned = signature.sign(setTo, cookiesecret + ip); - res.cookie('AUTH_COOKIE', cookiesigned, { maxAge: Math.pow(10, 10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - //updated username in the users table, but not yet on posts - let sql = `update ipost.posts set post_user_name=? where post_user_name=?;`; //change username of every past post sent - let values = [req.body.newUsername, res.locals.username, hashed_pw]; - con.query(sql, values, function (err, result) { - res.json({ "success": "successfully changed username" }); //done - }); - }); - }); - } - else { - res.json({ "error": "invalid password" }); - } - }); -}); -/* - -END /API/* - -*/ -router.get("/users/*", async function (req, res) { - if (!increaseUSERCall(req, res)) - return; - res.sendFile(dir + "views/otheruser.html"); -}); -router.get("/css/*", (request, response) => { - if (!increaseUSERCall(request, response)) - return; - if (existsSync(__dirname + request.originalUrl)) { - response.sendFile(__dirname + request.originalUrl); - } - else { - response.status(404).send("no file with that name found"); - } - return; -}); -router.get("/js/*", (request, response) => { - if (!increaseUSERCall(request, response)) - return; - if (existsSync(__dirname + request.originalUrl)) { - response.sendFile(__dirname + request.originalUrl); - } - else { - response.status(404).send("no file with that name found"); - } - return; -}); -router.get("/images/*", (request, response) => { - if (!increaseUSERCall(request, response)) - return; - if (existsSync(__dirname + request.originalUrl)) { - response.sendFile(__dirname + request.originalUrl); - } - else { - response.status(404).send("no file with that name found"); - } - return; -}); -router.get("/avatars/*", (request, response, next) => { - if (!increaseUSERCall(request, response)) - return; - response.set('Cache-Control', 'public, max-age=2592000'); //cache it for one month-ish - let originalUrl = request.originalUrl.split("?").shift(); - if (existsSync(dir + originalUrl + ".png")) { - return response.sendFile(dir + originalUrl + ".png"); - } - if (existsSync(dir + originalUrl)) { - return response.sendFile(dir + originalUrl); - } - response.status(404).send("No avatar with that name found"); -}); -router.get("/logout", async function (req, res) { - res.cookie("AUTH_COOKIE", "", { maxAge: 0, httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - res.redirect("/"); -}); -router.get("/*", (request, response, next) => { - if (!increaseUSERCall(request, response)) - return; - let originalUrl = request.originalUrl.split("?").shift(); - if (existsSync(dir + "views/" + originalUrl + ".html")) { - return response.sendFile(dir + "views/" + originalUrl + ".html"); - } - if (existsSync(dir + "views" + originalUrl)) { - return response.sendFile(dir + "views" + originalUrl); - } - if (existsSync(dir + "views" + originalUrl + ".html")) { - return response.sendFile(dir + "views" + originalUrl + ".html"); - } - if (existsSync(dir + "views" + originalUrl)) { - return response.sendFile(dir + "views" + originalUrl); - } - response.status(404).send("No file with that name found"); -}); -router.post("/register", async function (req, res) { - for (let i = 0; i < 10; i++) { //don't want people spam registering - if (!increaseAPICall(req, res)) - return; - } - res.status(200); - if ((typeof req.body.user) != "string") { - res.json({ "error": "incorrect username" }); - return; - } - if ((typeof req.body.pass) != "string") { - res.json({ "error": "incorrect password" }); - return; - } - let username = req.body.user.toString(); - username = username.replace(/\s/gi, ""); - let password = req.body.pass.toString(); - if (!username) { - res.status(400); - res.redirect("/register?success=false&reason=username"); - return; - } - if (username == "") { - res.status(400); - res.redirect("/register?success=false&reason=username"); - return; - } - if (password.length < 10) { - res.status(400); - res.send("password is too short"); - return; - } - if (username.length > 25) { - res.status(400); - res.send("username is too long"); - return; - } - if (username.search("@") != -1) { - res.status(400); - res.send("username can't contain @-characters"); - return; - } - if (!password) { - res.status(400); - res.redirect("/register?success=false&reason=password"); - return; - } - let userexistssql = `SELECT User_Name from ipost.users where User_Name = ?`; - con.query(userexistssql, [encodeURIComponent(username)], function (error, result) { - if (result && result[0] && result[0].User_Name) { - res.status(400); - res.redirect("/register?success=false&reason=already_exists"); - return; - } - let less_hashed_pw = SHA.SHA256(password, username, HASHES_DIFF); - let hashed_pw = SHA.SHA256(less_hashed_pw, username, HASHES_COOKIE); - let ip = getIP(req); - let setTo = username + " " + SHA.SHA256(password, username, HASHES_COOKIE); - let cookiesigned = signature.sign(setTo, cookiesecret + ip); - ip = SHA.SHA256(ip, setTo, HASHES_DB); - const default_settings = {}; - let values = [encodeURIComponent(username), hashed_pw, Date.now(), ip, ip, JSON.stringify(default_settings)]; - let sql = `INSERT INTO ipost.users (User_Name, User_PW, User_CreationStamp, User_CreationIP, User_LastIP, User_Settings) VALUES (?, ?, ?, ?, ?, ?, ?, ?);`; - con.query(sql, values, function (err, result) { - if (err) - throw err; - res.cookie('AUTH_COOKIE', cookiesigned, { maxAge: Math.pow(10, 10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - res.redirect("/user?success=true"); - }); - }); -}); -router.post("/login", async function (req, res) { - if (!increaseAPICall(req, res)) - return; - if (!increaseAPICall(req, res)) - return; - //login is counted twice (think of bruteforces man) - if ((typeof req.body.user) != "string") { - res.json({ "error": "incorrect username" }); - return; - } - if ((typeof req.body.pass) != "string") { - res.json({ "error": "incorrect password" }); - return; - } - if (!req.body.user) { - res.status(400); - res.send("no username given"); - return; - } - if (!req.body.pass) { - res.status(400); - res.send("no password given"); - return; - } - let username = req.body.user.toString(); - username = username.replace(" ", ""); - let password = req.body.pass.toString(); - if (!username) { - res.status(400); - res.send("no username given"); - return; - } - if (username.length > 25) { - res.status(400); - res.send("username is too long"); - return; - } - if (password.length < 10) { - res.status(400); - res.send("password is too short"); - return; - } - if (!password) { - res.status(400); - res.send("no password given"); - return; - } - let less_hashed_pw = SHA.SHA256(password, username, HASHES_DIFF); - let hashed_pw = SHA.SHA256(less_hashed_pw, username, HASHES_COOKIE); - let userexistssql = `SELECT * from ipost.users where User_Name = ? and User_PW = ?;`; - con.query(userexistssql, [encodeURIComponent(username), hashed_pw], function (error, result) { - if (result && result[0]) { - let ip = getIP(req); - let setTo = username + " " + SHA.SHA256(password, username, HASHES_COOKIE); - let cookiesigned = signature.sign(setTo, cookiesecret + ip); - res.cookie('AUTH_COOKIE', cookiesigned, { maxAge: Math.pow(10, 10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS }); - ip = SHA.SHA256(ip, setTo, HASHES_DB); - if (result[0].User_LastIP != ip) { - let sql = `update ipost.users set User_LastIP = ? where User_Name = ?;`; - con.query(sql, [ip, encodeURIComponent(username)], function (error, result) { - if (error) - throw error; - }); - } - res.redirect("/user?success=true"); - } - else { - res.redirect("/login?success=false?reason=noUser"); - } - }); -}); -console.log(5, "finished loading routes"); -app.use(router); -const httpServer = http.createServer(app); -httpServer.listen(config["ports"]["http"], function () { - console.log(5, "HTTP Server is listening"); -}); -const privateKey = readFileSync(config["ssl"]["privateKey"]).toString(); -const certificate = readFileSync(config["ssl"]["certificate"]).toString(); -const credentials = { key: privateKey, cert: certificate }; -var httpsServer; -if (DID_I_FINALLY_ADD_HTTPS) { - httpsServer = https.createServer(credentials, app); - httpsServer.listen(config["ports"]["https"], function () { - console.log(5, "HTTPS Server is listening"); - }); -} -else { - httpsServer = httpServer; -} -wss = new WebSocket({ - server: httpsServer, - perMessageDeflate: { - zlibDeflateOptions: { - chunkSize: 1024, - memLevel: 7, - level: 3 - }, - zlibInflateOptions: { - chunkSize: 10 * 1024 - }, - clientNoContextTakeover: true, - serverNoContextTakeover: true, - serverMaxWindowBits: 10, - concurrencyLimit: 10, - threshold: 1024 * 16 - } -}); -wss.on("connection", function connection(ws) { - ws.channel = "everyone"; - ws.on("message", function incoming(message) { - message = JSON.parse(message); - if (message.id == "switchChannel") { - ws.channel = decodeURIComponent(message.data); - } - }); -}); -commonfunctions.wss = wss; -console.log(5, "starting up all services");