This repository has been archived on 2024-09-11. You can view files and clone it, but cannot push or open issues or pull requests.
svrjs-blog-newsletter/backend/serverSideScript.js
2024-05-26 22:54:55 +02:00

258 lines
8.4 KiB
JavaScript

disableEndElseCallbackExecute = true;
var emailregex = /(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/i
var querystring = require("querystring");
var dns = require("dns");
var MongoClient = require('mongodb').MongoClient;
var mongoURL = "mongodb://localhost/newsletter";
var dbname = "newsletter";
var redirectURL = "https://blog.svrjs.org";
var allowedHosts = [
"https://blog.svrjs.org"
];
function antiXSS(string) {
return string.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
}
function generateUnsubscribeID() {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = "";
for (let i = 0; i < 32; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
function generateUniqueUnsubscribeID(db, callback) {
var id = generateUnsubscribeID();
db.collection("emails").find({
unsubscribeId: id
}).toArray(function (err, result) {
if (err) {
callServerError(500, err);
return;
}
if (result.length > 0) {
generateUnsubscribeID(db);
} else {
callback(id);
}
});
}
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function connectMongo(callback) {
// customvar3 is a MongoDB database object
if (customvar3) {
callback(customvar3);
} else {
MongoClient.connect(mongoURL, function (err, db) {
if (err) {
callServerError(500, err);
return;
}
var dbo = db.db(dbname);
dbo.createCollection("emails", function (err, dbres) {
customvar3 = dbo;
callback(dbo);
});
});
}
}
function formatTemplate(templateName, templateData, callback) {
fs.readFile(__dirname + "/../templates/" + templateName + ".template", function (err, data) {
if (err) {
callServerError(500, err);
return;
}
var tD = data.toString();
Object.keys(templateData).forEach(function (key) {
tD = tD.replace(new RegExp("\\{\\{" + escapeRegExp(key) + "\\}\\}", "g"), templateData[key]);
});
callback(tD);
});
}
if (href == "/subscribe.svr") {
if (req.method != "POST") {
callServerError(405, {
"Allow": "POST"
});
return;
}
var baseURL = (req.socket.encrypted ? "https" : "http") + "://" + (req.headers.host ? req.headers.host : req.socket.localAddress);
var isReferrerValid = false;
if ((req.headers.referer + "/").substring(0, baseURL.length + 1) == (baseURL + "/")) isReferrerValid = true;
if (!isReferrerValid) {
allowedHosts.every(function (allowedHost) {
allowedHost = allowedHost.replace(/\/+$/, "");
if ((req.headers.referer + "/").substring(0, allowedHost.length + 1) == (allowedHost + "/")) {
isReferrerValid = true;
return false;
} else {
return true;
}
});
}
if (!isReferrerValid) {
formatTemplate("index.html", {
"title": "Invalid referrer",
"paragraph": "<p>Invalid referrer has been detected. There may be a CSRF attack.</p>"
}, function (data) {
res.writeHead(400, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
return;
}
var postdata = "";
req.on("data", function (data) {
postdata += data.toString();
});
req.on("end", function () {
postdata = querystring.parse(postdata);
if (!postdata.email) {
formatTemplate("index.html", {
"title": "No email address",
"paragraph": "<p>You didn't send any email address.</p>"
}, function (data) {
res.writeHead(400, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
return;
} else if (!postdata.email.match(emailregex)) {
formatTemplate("index.html", {
"title": "Invalid email address",
"paragraph": "<p>The email address you sent is invalid.</p>"
}, function (data) {
res.writeHead(400, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
return;
} else {
dns.resolveMx(postdata.email.match(/@([\s\S]*)/)[1], function (err, mxRecords) {
if (err || mxRecords.length == 0) {
formatTemplate("index.html", {
"title": "Your email domain is misconfigured",
"paragraph": "<p>The server has determined, that your email domain is misconfigured (MX records not found). Contact the administrator of the domain for the assistance.</p>"
}, function (data) {
res.writeHead(400, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
return;
}
connectMongo(function (db) {
db.collection("emails").find({
email: postdata.email
}).toArray(function (err, result) {
if (err) {
callServerError(500, err);
return;
}
if (result.length > 0) {
formatTemplate("index.html", {
"title": "You have already subscribed to the newsletter",
"paragraph": "<p>You have already subscribed to the newsletter.</p>"
}, function (data) {
res.writeHead(200, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
} else {
generateUniqueUnsubscribeID(db, function (id) {
db.collection("emails").insertOne({
email: postdata.email,
unsubscribeId: id
}, function (err, dbres) {
if (err) {
callServerError(500, err);
return;
}
formatTemplate("index.html", {
"title": "Thank you for subscribing to our newsletter!",
"paragraph": "<p>You can unsubscribe from the newsletter using <a href=\"" + antiXSS(baseURL + "/unsubscribe.svr?id=" + encodeURIComponent(id)) + "\">this link</a>.</p>"
}, function (data) {
res.writeHead(200, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
});
});
}
});
});
});
}
});
} else if (href == "/unsubscribe.svr") {
if (!uobject.query.id) {
formatTemplate("index.html", {
"title": "Invalid unsubscription link",
"paragraph": "<p>You didn't provide the unsubscription ID.</p>"
}, function (data) {
res.writeHead(400, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
}
connectMongo(function (db) {
db.collection("emails").find({
unsubscribeId: uobject.query.id
}).toArray(function (err, result) {
if (err) {
callServerError(500, err);
return;
}
if (result.length == 0) {
formatTemplate("index.html", {
"title": "Invalid unsubscription link",
"paragraph": "<p>You have either already unsubscribed from the newsletter, or the unsubscription ID is invalid.</p>"
}, function (data) {
res.writeHead(400, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
} else {
db.collection("emails").deleteOne({
unsubscribeId: uobject.query.id
}, function (err, dbres) {
if (err) {
callServerError(500, err);
return;
}
formatTemplate("index.html", {
"title": "You have been unsubscribed from the newsletter!",
"paragraph": "<p>You have been unsubscribed from the newsletter.</p>"
}, function (data) {
res.writeHead(200, {
"Content-Type": "text/html; charset=utf-8"
});
res.end(data);
});
});
}
});
});
} else if (href == "/") {
redirect(redirectURL);
} else {
elseCallback();
}