forked from svrjs/svrjs
Lint out the codebase.
This commit is contained in:
parent
1929641ba7
commit
a49dba73fe
8 changed files with 374 additions and 276 deletions
|
@ -1,9 +1,11 @@
|
|||
const http = require("http");
|
||||
const fs = require("fs");
|
||||
const net = require("net");
|
||||
const generateErrorStack = require("../utils/generateErrorStack.js");
|
||||
const serverHTTPErrorDescs = require("../res/httpErrorDescriptions.js");
|
||||
const fixNodeMojibakeURL = require("../utils/urlMojibakeFixer.js");
|
||||
const getOS = require("../utils/getOS.js");
|
||||
const ipMatch = require("../utils/ipMatch.js");
|
||||
const svrjsInfo = require("../../svrjs.json");
|
||||
const version = svrjsInfo.version;
|
||||
|
||||
|
@ -295,15 +297,15 @@ module.exports = (req, res, logFacilities, config, next) => {
|
|||
"Host name rewritten: " + oldHostHeader + " => " + req.headers.host,
|
||||
);
|
||||
|
||||
// Header and footer placeholders
|
||||
res.head = "";
|
||||
res.foot = "";
|
||||
// Header and footer placeholders
|
||||
res.head = "";
|
||||
res.foot = "";
|
||||
|
||||
res.responseEnd = (body) => {
|
||||
// If body is Buffer, then it is converted to String anyway.
|
||||
res.write(head + body + foot);
|
||||
res.end();
|
||||
}
|
||||
res.responseEnd = (body) => {
|
||||
// If body is Buffer, then it is converted to String anyway.
|
||||
res.write(res.head + body + res.foot);
|
||||
res.end();
|
||||
};
|
||||
|
||||
// Server error calling method
|
||||
res.error = (errorCode, extName, stack, ch) => {
|
||||
|
@ -670,8 +672,16 @@ module.exports = (req, res, logFacilities, config, next) => {
|
|||
};
|
||||
|
||||
try {
|
||||
res.head = fs.existsSync("./.head") ? fs.readFileSync("./.head").toString() : (fs.existsSync("./head.html") ? fs.readFileSync("./head.html").toString() : ""); // header
|
||||
res.foot = fs.existsSync("./.foot") ? fs.readFileSync("./.foot").toString() : (fs.existsSync("./foot.html") ? fs.readFileSync("./foot.html").toString() : ""); // footer
|
||||
res.head = fs.existsSync("./.head")
|
||||
? fs.readFileSync("./.head").toString()
|
||||
: fs.existsSync("./head.html")
|
||||
? fs.readFileSync("./head.html").toString()
|
||||
: ""; // header
|
||||
res.foot = fs.existsSync("./.foot")
|
||||
? fs.readFileSync("./.foot").toString()
|
||||
: fs.existsSync("./foot.html")
|
||||
? fs.readFileSync("./foot.html").toString()
|
||||
: ""; // footer
|
||||
} catch (err) {
|
||||
res.error(500, err);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,12 @@ module.exports = (req, res, logFacilities, config, next) => {
|
|||
let fromMain = !(config.secure && !req.socket.encrypted);
|
||||
|
||||
// Handle redirects to HTTPS
|
||||
if (config.secure && !fromMain && !config.disableNonEncryptedServer && !config.disableToHTTPSRedirect) {
|
||||
if (
|
||||
config.secure &&
|
||||
!fromMain &&
|
||||
!config.disableNonEncryptedServer &&
|
||||
!config.disableToHTTPSRedirect
|
||||
) {
|
||||
var hostx = req.headers.host;
|
||||
if (hostx === undefined) {
|
||||
logFacilities.errmessage("Host header is missing.");
|
||||
|
@ -17,7 +22,13 @@ module.exports = (req, res, logFacilities, config, next) => {
|
|||
return;
|
||||
}
|
||||
|
||||
var isPublicServer = !(req.socket.realRemoteAddress ? req.socket.realRemoteAddress : req.socket.remoteAddress).match(/^(?:localhost$|::1$|f[c-d][0-9a-f]{2}:|(?:::ffff:)?(?:(?:127|10)\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|192\.168\.[0-9]{1,3}\.[0-9]{1,3}|172\.(?:1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3})$)/i);
|
||||
var isPublicServer = !(
|
||||
req.socket.realRemoteAddress
|
||||
? req.socket.realRemoteAddress
|
||||
: req.socket.remoteAddress
|
||||
).match(
|
||||
/^(?:localhost$|::1$|f[c-d][0-9a-f]{2}:|(?:::ffff:)?(?:(?:127|10)\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|192\.168\.[0-9]{1,3}\.[0-9]{1,3}|172\.(?:1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3})$)/i,
|
||||
);
|
||||
|
||||
var destinationPort = 0;
|
||||
|
||||
|
@ -26,13 +37,21 @@ module.exports = (req, res, logFacilities, config, next) => {
|
|||
var hostPort = parsedHostx[2] ? parseInt(parsedHostx[2]) : 80;
|
||||
if (isNaN(hostPort)) hostPort = 80;
|
||||
|
||||
if (hostPort == config.port || (config.port == config.pubport && !isPublicServer)) {
|
||||
if (
|
||||
hostPort == config.port ||
|
||||
(config.port == config.pubport && !isPublicServer)
|
||||
) {
|
||||
destinationPort = config.sport;
|
||||
} else {
|
||||
destinationPort = config.spubport;
|
||||
}
|
||||
|
||||
redirect("https://" + hostname + (destinationPort == 443 ? "" : (":" + destinationPort)) + req.url);
|
||||
res.redirect(
|
||||
"https://" +
|
||||
hostname +
|
||||
(destinationPort == 443 ? "" : ":" + destinationPort) +
|
||||
req.url,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -40,13 +59,23 @@ module.exports = (req, res, logFacilities, config, next) => {
|
|||
if (config.wwwredirect) {
|
||||
let hostname = req.headers.host.split(":");
|
||||
let hostport = null;
|
||||
if (hostname.length > 1 && (hostname[0] != "[" || hostname[hostname.length - 1] != "]")) hostport = hostname.pop();
|
||||
if (
|
||||
hostname.length > 1 &&
|
||||
(hostname[0] != "[" || hostname[hostname.length - 1] != "]")
|
||||
)
|
||||
hostport = hostname.pop();
|
||||
hostname = hostname.join(":");
|
||||
if (hostname == domain && hostname.indexOf("www.") != 0) {
|
||||
res.redirect((req.socket.encrypted ? "https" : "http") + "://www." + hostname + (hostport ? ":" + hostport : "") + req.url.replace(/\/+/g, "/"));
|
||||
if (hostname == config.domain && hostname.indexOf("www.") != 0) {
|
||||
res.redirect(
|
||||
(req.socket.encrypted ? "https" : "http") +
|
||||
"://www." +
|
||||
hostname +
|
||||
(hostport ? ":" + hostport : "") +
|
||||
req.url.replace(/\/+/g, "/"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
const { emitWarning } = require("process");
|
||||
const sanitizeURL = require("../utils/urlSanitizer.js");
|
||||
const url = require("url");
|
||||
|
||||
|
|
|
@ -1,116 +1,147 @@
|
|||
const url = require("url");
|
||||
const createRegex = require("../utils/createRegex.js");
|
||||
const ipMatch = require("../utils/ipMatch.js");
|
||||
const sanitizeURL = require("../utils/urlSanitizer.js");
|
||||
|
||||
module.exports = (req, res, logFacilities, config, next) => {
|
||||
const matchHostname = (hostname) => {
|
||||
if (typeof hostname == "undefined" || hostname == "*") {
|
||||
return true;
|
||||
} else if (
|
||||
req.headers.host &&
|
||||
hostname.indexOf("*.") == 0 &&
|
||||
hostname != "*."
|
||||
) {
|
||||
const hostnamesRoot = hostname.substring(2);
|
||||
if (
|
||||
req.headers.host == hostnamesRoot ||
|
||||
(req.headers.host.length > hostnamesRoot.length &&
|
||||
req.headers.host.indexOf("." + hostnamesRoot) ==
|
||||
req.headers.host.length - hostnamesRoot.length - 1)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
} else if (req.headers.host && req.headers.host == hostname) {
|
||||
return true;
|
||||
}
|
||||
const matchHostname = (hostname) => {
|
||||
if (typeof hostname == "undefined" || hostname == "*") {
|
||||
return true;
|
||||
} else if (
|
||||
req.headers.host &&
|
||||
hostname.indexOf("*.") == 0 &&
|
||||
hostname != "*."
|
||||
) {
|
||||
const hostnamesRoot = hostname.substring(2);
|
||||
if (
|
||||
req.headers.host == hostnamesRoot ||
|
||||
(req.headers.host.length > hostnamesRoot.length &&
|
||||
req.headers.host.indexOf("." + hostnamesRoot) ==
|
||||
req.headers.host.length - hostnamesRoot.length - 1)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
} else if (req.headers.host && req.headers.host == hostname) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Add web root postfixes
|
||||
if (!req.isProxy) {
|
||||
let preparedReqUrl3 = config.allowPostfixDoubleSlashes
|
||||
? req.parsedURL.pathname.replace(/\/+/, "/") +
|
||||
req.parsedURL.search +
|
||||
req.parsedURL.hash
|
||||
: req.url;
|
||||
let urlWithPostfix = preparedReqUrl3;
|
||||
let postfixPrefix = "";
|
||||
config.wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) {
|
||||
if (preparedReqUrl3.indexOf(currentPostfixPrefix) == 0) {
|
||||
if (currentPostfixPrefix.match(/\/+$/))
|
||||
postfixPrefix = currentPostfixPrefix.replace(/\/+$/, "");
|
||||
else if (
|
||||
urlWithPostfix.length == currentPostfixPrefix.length ||
|
||||
urlWithPostfix[currentPostfixPrefix.length] == "?" ||
|
||||
urlWithPostfix[currentPostfixPrefix.length] == "/" ||
|
||||
urlWithPostfix[currentPostfixPrefix.length] == "#"
|
||||
)
|
||||
postfixPrefix = currentPostfixPrefix;
|
||||
else return true;
|
||||
urlWithPostfix = urlWithPostfix.substring(postfixPrefix.length);
|
||||
return false;
|
||||
};
|
||||
|
||||
// Add web root postfixes
|
||||
if (!req.isProxy) {
|
||||
let preparedReqUrl3 = (config.allowPostfixDoubleSlashes ? (req.parsedURL.pathname.replace(/\/+/,"/") + req.parsedURL.search + req.parsedURL.hash) : req.url);
|
||||
let urlWithPostfix = preparedReqUrl3;
|
||||
let postfixPrefix = "";
|
||||
config.wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) {
|
||||
if (preparedReqUrl3.indexOf(currentPostfixPrefix) == 0) {
|
||||
if (currentPostfixPrefix.match(/\/+$/)) postfixPrefix = currentPostfixPrefix.replace(/\/+$/, "");
|
||||
else if (urlWithPostfix.length == currentPostfixPrefix.length || urlWithPostfix[currentPostfixPrefix.length] == "?" || urlWithPostfix[currentPostfixPrefix.length] == "/" || urlWithPostfix[currentPostfixPrefix.length] == "#") postfixPrefix = currentPostfixPrefix;
|
||||
else return true;
|
||||
urlWithPostfix = urlWithPostfix.substring(postfixPrefix.length);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
config.wwwrootPostfixesVHost.every(function (postfixEntry) {
|
||||
if (matchHostname(postfixEntry.host) && ipMatch(postfixEntry.ip, req.socket ? req.socket.localAddress : undefined) && !(postfixEntry.skipRegex && preparedReqUrl3.match(createRegex(postfixEntry.skipRegex)))) {
|
||||
urlWithPostfix = postfixPrefix + "/" + postfixEntry.postfix + urlWithPostfix;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (urlWithPostfix != preparedReqUrl3) {
|
||||
logFacilities.resmessage("Added web root postfix: " + req.url + " => " + urlWithPostfix);
|
||||
req.url = urlWithPostfix;
|
||||
try {
|
||||
req.parsedURL = new URL(
|
||||
req.url,
|
||||
"http" +
|
||||
(req.socket.encrypted ? "s" : "") +
|
||||
"://" +
|
||||
(req.headers.host
|
||||
? req.headers.host
|
||||
: config.domain
|
||||
? config.domain
|
||||
: "unknown.invalid"),
|
||||
);
|
||||
} catch (err) {
|
||||
res.error(400, err);
|
||||
return;
|
||||
}
|
||||
|
||||
let href = req.parsedURL.pathname + req.parsedURL.search;
|
||||
|
||||
var sHref = sanitizeURL(href, allowDoubleSlashes);
|
||||
var preparedReqUrl2 = req.parsedURL.pathname + req.parsedURL.search + req.parsedURL.hash;
|
||||
|
||||
if (req.url != preparedReqUrl2 || sHref != href.replace(/\/\.(?=\/|$)/g, "/").replace(/\/+/g, "/")) {
|
||||
res.error(403);
|
||||
logFacilities.errmessage("Content blocked.");
|
||||
return;
|
||||
} else if (sHref != href) {
|
||||
var rewrittenAgainURL = new url.Url();
|
||||
rewrittenAgainURL.path = null;
|
||||
rewrittenAgainURL.href = null;
|
||||
rewrittenAgainURL.pathname = sHref;
|
||||
rewrittenAgainURL.hostname = null;
|
||||
rewrittenAgainURL.host = null;
|
||||
rewrittenAgainURL.port = null;
|
||||
rewrittenAgainURL.protocol = null;
|
||||
rewrittenAgainURL.slashes = null;
|
||||
rewrittenAgainURL = url.format(rewrittenAgainURL);
|
||||
logFacilities.resmessage("URL sanitized: " + req.url + " => " + rewrittenAgainURL);
|
||||
req.url = rewrittenAgainURL;
|
||||
try {
|
||||
req.parsedURL = new URL(
|
||||
req.url,
|
||||
"http" +
|
||||
(req.socket.encrypted ? "s" : "") +
|
||||
"://" +
|
||||
(req.headers.host
|
||||
? req.headers.host
|
||||
: config.domain
|
||||
? config.domain
|
||||
: "unknown.invalid"),
|
||||
);
|
||||
} catch (err) {
|
||||
res.error(400, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
config.wwwrootPostfixesVHost.every(function (postfixEntry) {
|
||||
if (
|
||||
matchHostname(postfixEntry.host) &&
|
||||
ipMatch(
|
||||
postfixEntry.ip,
|
||||
req.socket ? req.socket.localAddress : undefined,
|
||||
) &&
|
||||
!(
|
||||
postfixEntry.skipRegex &&
|
||||
preparedReqUrl3.match(createRegex(postfixEntry.skipRegex))
|
||||
)
|
||||
) {
|
||||
urlWithPostfix =
|
||||
postfixPrefix + "/" + postfixEntry.postfix + urlWithPostfix;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (urlWithPostfix != preparedReqUrl3) {
|
||||
logFacilities.resmessage(
|
||||
"Added web root postfix: " + req.url + " => " + urlWithPostfix,
|
||||
);
|
||||
req.url = urlWithPostfix;
|
||||
try {
|
||||
req.parsedURL = new URL(
|
||||
req.url,
|
||||
"http" +
|
||||
(req.socket.encrypted ? "s" : "") +
|
||||
"://" +
|
||||
(req.headers.host
|
||||
? req.headers.host
|
||||
: config.domain
|
||||
? config.domain
|
||||
: "unknown.invalid"),
|
||||
);
|
||||
} catch (err) {
|
||||
res.error(400, err);
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
let href = req.parsedURL.pathname + req.parsedURL.search;
|
||||
|
||||
var sHref = sanitizeURL(href, config.allowDoubleSlashes);
|
||||
var preparedReqUrl2 =
|
||||
req.parsedURL.pathname + req.parsedURL.search + req.parsedURL.hash;
|
||||
|
||||
if (
|
||||
req.url != preparedReqUrl2 ||
|
||||
sHref != href.replace(/\/\.(?=\/|$)/g, "/").replace(/\/+/g, "/")
|
||||
) {
|
||||
res.error(403);
|
||||
logFacilities.errmessage("Content blocked.");
|
||||
return;
|
||||
} else if (sHref != href) {
|
||||
var rewrittenAgainURL = new url.Url();
|
||||
rewrittenAgainURL.path = null;
|
||||
rewrittenAgainURL.href = null;
|
||||
rewrittenAgainURL.pathname = sHref;
|
||||
rewrittenAgainURL.hostname = null;
|
||||
rewrittenAgainURL.host = null;
|
||||
rewrittenAgainURL.port = null;
|
||||
rewrittenAgainURL.protocol = null;
|
||||
rewrittenAgainURL.slashes = null;
|
||||
rewrittenAgainURL = url.format(rewrittenAgainURL);
|
||||
logFacilities.resmessage(
|
||||
"URL sanitized: " + req.url + " => " + rewrittenAgainURL,
|
||||
);
|
||||
req.url = rewrittenAgainURL;
|
||||
try {
|
||||
req.parsedURL = new URL(
|
||||
req.url,
|
||||
"http" +
|
||||
(req.socket.encrypted ? "s" : "") +
|
||||
"://" +
|
||||
(req.headers.host
|
||||
? req.headers.host
|
||||
: config.domain
|
||||
? config.domain
|
||||
: "unknown.invalid"),
|
||||
);
|
||||
} catch (err) {
|
||||
res.error(400, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
const os = require("os");
|
||||
|
||||
function createRegex(regex, isPath) {
|
||||
var regexStrMatch = regex.match(/^\/((?:\\.|[^\/\\])*)\/([a-zA-Z0-9]*)$/);
|
||||
if (!regexStrMatch) throw new Error("Invalid regular expression: " + regex);
|
||||
var searchString = regexStrMatch[1];
|
||||
var modifiers = regexStrMatch[2];
|
||||
if (isPath && !modifiers.match(/i/i) && os.platform() == "win32") modifiers += "i";
|
||||
return new RegExp(searchString, modifiers);
|
||||
}
|
||||
const regexStrMatch = regex.match(/^\/((?:\\.|[^\/\\])*)\/([a-zA-Z0-9]*)$/);
|
||||
if (!regexStrMatch) throw new Error("Invalid regular expression: " + regex);
|
||||
const searchString = regexStrMatch[1];
|
||||
let modifiers = regexStrMatch[2];
|
||||
if (isPath && !modifiers.match(/i/i) && os.platform() == "win32")
|
||||
modifiers += "i";
|
||||
return new RegExp(searchString, modifiers);
|
||||
}
|
||||
|
||||
module.exports = createRegex;
|
||||
module.exports = createRegex;
|
||||
|
|
|
@ -1,78 +1,82 @@
|
|||
// Function to check if IPs are equal
|
||||
function ipMatch(IP1, IP2) {
|
||||
if (!IP1) return true;
|
||||
if (!IP2) return false;
|
||||
|
||||
// Function to normalize IPv4 address (remove leading zeros)
|
||||
function normalizeIPv4Address(address) {
|
||||
return address.replace(/(^|\.)(?:0(?!\.|$))+/g, "$1");
|
||||
}
|
||||
|
||||
// Function to expand IPv6 address to full format
|
||||
function expandIPv6Address(address) {
|
||||
var fullAddress = "";
|
||||
var expandedAddress = "";
|
||||
var validGroupCount = 8;
|
||||
var validGroupSize = 4;
|
||||
|
||||
var ipv4 = "";
|
||||
var extractIpv4 = /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/;
|
||||
var validateIpv4 = /((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})/;
|
||||
|
||||
if (validateIpv4.test(address)) {
|
||||
var oldGroups = address.match(extractIpv4);
|
||||
for (var i = 1; i < oldGroups.length; i++) {
|
||||
ipv4 += ("00" + (parseInt(oldGroups[i], 10).toString(16))).slice(-2) + (i == 2 ? ":" : "");
|
||||
}
|
||||
address = address.replace(extractIpv4, ipv4);
|
||||
}
|
||||
|
||||
if (address.indexOf("::") == -1) {
|
||||
fullAddress = address;
|
||||
} else {
|
||||
var sides = address.split("::");
|
||||
var groupsPresent = 0;
|
||||
sides.forEach(function (side) {
|
||||
groupsPresent += side.split(":").length;
|
||||
});
|
||||
fullAddress += sides[0] + ":";
|
||||
if (validGroupCount - groupsPresent > 1) {
|
||||
fullAddress += "0000:".repeat(validGroupCount - groupsPresent);
|
||||
}
|
||||
fullAddress += sides[1];
|
||||
}
|
||||
var groups = fullAddress.split(":");
|
||||
for (var i = 0; i < validGroupCount; i++) {
|
||||
if (groups[i].length < validGroupSize) {
|
||||
groups[i] = "0".repeat(validGroupSize - groups[i].length) + groups[i];
|
||||
}
|
||||
expandedAddress += (i != validGroupCount - 1) ? groups[i] + ":" : groups[i];
|
||||
}
|
||||
return expandedAddress;
|
||||
}
|
||||
|
||||
// Normalize or expand IP addresses
|
||||
IP1 = IP1.toLowerCase();
|
||||
if (IP1 == "localhost") IP1 = "::1";
|
||||
if (IP1.indexOf("::ffff:") == 0) IP1 = IP1.substring(7);
|
||||
if (IP1.indexOf(":") > -1) {
|
||||
IP1 = expandIPv6Address(IP1);
|
||||
} else {
|
||||
IP1 = normalizeIPv4Address(IP1);
|
||||
}
|
||||
|
||||
IP2 = IP2.toLowerCase();
|
||||
if (IP2 == "localhost") IP2 = "::1";
|
||||
if (IP2.indexOf("::ffff:") == 0) IP2 = IP2.substring(7);
|
||||
if (IP2.indexOf(":") > -1) {
|
||||
IP2 = expandIPv6Address(IP2);
|
||||
} else {
|
||||
IP2 = normalizeIPv4Address(IP2);
|
||||
}
|
||||
|
||||
// Check if processed IPs are equal
|
||||
if (IP1 == IP2) return true;
|
||||
else return false;
|
||||
if (!IP1) return true;
|
||||
if (!IP2) return false;
|
||||
|
||||
// Function to normalize IPv4 address (remove leading zeros)
|
||||
function normalizeIPv4Address(address) {
|
||||
return address.replace(/(^|\.)(?:0(?!\.|$))+/g, "$1");
|
||||
}
|
||||
|
||||
module.exports = ipMatch;
|
||||
// Function to expand IPv6 address to full format
|
||||
function expandIPv6Address(address) {
|
||||
let fullAddress = "";
|
||||
let expandedAddress = "";
|
||||
let validGroupCount = 8;
|
||||
let validGroupSize = 4;
|
||||
|
||||
let ipv4 = "";
|
||||
const extractIpv4 =
|
||||
/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/;
|
||||
const validateIpv4 =
|
||||
/((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})/;
|
||||
|
||||
if (validateIpv4.test(address)) {
|
||||
const oldGroups = address.match(extractIpv4);
|
||||
for (let i = 1; i < oldGroups.length; i++) {
|
||||
ipv4 +=
|
||||
("00" + parseInt(oldGroups[i], 10).toString(16)).slice(-2) +
|
||||
(i == 2 ? ":" : "");
|
||||
}
|
||||
address = address.replace(extractIpv4, ipv4);
|
||||
}
|
||||
|
||||
if (address.indexOf("::") == -1) {
|
||||
fullAddress = address;
|
||||
} else {
|
||||
const sides = address.split("::");
|
||||
let groupsPresent = 0;
|
||||
sides.forEach((side) => {
|
||||
groupsPresent += side.split(":").length;
|
||||
});
|
||||
fullAddress += sides[0] + ":";
|
||||
if (validGroupCount - groupsPresent > 1) {
|
||||
fullAddress += "0000:".repeat(validGroupCount - groupsPresent);
|
||||
}
|
||||
fullAddress += sides[1];
|
||||
}
|
||||
let groups = fullAddress.split(":");
|
||||
for (let i = 0; i < validGroupCount; i++) {
|
||||
if (groups[i].length < validGroupSize) {
|
||||
groups[i] = "0".repeat(validGroupSize - groups[i].length) + groups[i];
|
||||
}
|
||||
expandedAddress += i != validGroupCount - 1 ? groups[i] + ":" : groups[i];
|
||||
}
|
||||
return expandedAddress;
|
||||
}
|
||||
|
||||
// Normalize or expand IP addresses
|
||||
IP1 = IP1.toLowerCase();
|
||||
if (IP1 == "localhost") IP1 = "::1";
|
||||
if (IP1.indexOf("::ffff:") == 0) IP1 = IP1.substring(7);
|
||||
if (IP1.indexOf(":") > -1) {
|
||||
IP1 = expandIPv6Address(IP1);
|
||||
} else {
|
||||
IP1 = normalizeIPv4Address(IP1);
|
||||
}
|
||||
|
||||
IP2 = IP2.toLowerCase();
|
||||
if (IP2 == "localhost") IP2 = "::1";
|
||||
if (IP2.indexOf("::ffff:") == 0) IP2 = IP2.substring(7);
|
||||
if (IP2.indexOf(":") > -1) {
|
||||
IP2 = expandIPv6Address(IP2);
|
||||
} else {
|
||||
IP2 = normalizeIPv4Address(IP2);
|
||||
}
|
||||
|
||||
// Check if processed IPs are equal
|
||||
if (IP1 == IP2) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
module.exports = ipMatch;
|
||||
|
|
|
@ -1,75 +1,77 @@
|
|||
const createRegex = require('../../src/utils/createRegex');
|
||||
const os = require('os');
|
||||
const createRegex = require("../../src/utils/createRegex");
|
||||
const os = require("os");
|
||||
|
||||
jest.mock('os', () => ({
|
||||
jest.mock("os", () => ({
|
||||
platform: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('createRegex', () => {
|
||||
describe("createRegex", () => {
|
||||
beforeEach(() => {
|
||||
os.platform.mockReset();
|
||||
});
|
||||
|
||||
test('should throw an error for invalid regular expression', () => {
|
||||
expect(() => createRegex('invalid/regex', false)).toThrow('Invalid regular expression: invalid/regex');
|
||||
test("should throw an error for invalid regular expression", () => {
|
||||
expect(() => createRegex("invalid/regex", false)).toThrow(
|
||||
"Invalid regular expression: invalid/regex",
|
||||
);
|
||||
});
|
||||
|
||||
test('should create a regular expression without modifiers', () => {
|
||||
const regex = createRegex('/test/', false);
|
||||
test("should create a regular expression without modifiers", () => {
|
||||
const regex = createRegex("/test/", false);
|
||||
expect(regex).toBeInstanceOf(RegExp);
|
||||
expect(regex.source).toBe('test');
|
||||
expect(regex.flags).toBe('');
|
||||
expect(regex.source).toBe("test");
|
||||
expect(regex.flags).toBe("");
|
||||
});
|
||||
|
||||
test('should create a regular expression with modifiers', () => {
|
||||
const regex = createRegex('/test/gi', false);
|
||||
test("should create a regular expression with modifiers", () => {
|
||||
const regex = createRegex("/test/gi", false);
|
||||
expect(regex).toBeInstanceOf(RegExp);
|
||||
expect(regex.source).toBe('test');
|
||||
expect(regex.flags).toBe('gi');
|
||||
expect(regex.source).toBe("test");
|
||||
expect(regex.flags).toBe("gi");
|
||||
});
|
||||
|
||||
test('should add "i" modifier for paths on Windows', () => {
|
||||
os.platform.mockReturnValue('win32');
|
||||
const regex = createRegex('/test/', true);
|
||||
os.platform.mockReturnValue("win32");
|
||||
const regex = createRegex("/test/", true);
|
||||
expect(regex).toBeInstanceOf(RegExp);
|
||||
expect(regex.source).toBe('test');
|
||||
expect(regex.flags).toBe('i');
|
||||
expect(regex.source).toBe("test");
|
||||
expect(regex.flags).toBe("i");
|
||||
});
|
||||
|
||||
test('should not add "i" modifier for paths on non-Windows platforms', () => {
|
||||
os.platform.mockReturnValue('linux');
|
||||
const regex = createRegex('/test/', true);
|
||||
os.platform.mockReturnValue("linux");
|
||||
const regex = createRegex("/test/", true);
|
||||
expect(regex).toBeInstanceOf(RegExp);
|
||||
expect(regex.source).toBe('test');
|
||||
expect(regex.flags).toBe('');
|
||||
expect(regex.source).toBe("test");
|
||||
expect(regex.flags).toBe("");
|
||||
});
|
||||
|
||||
test('should not add "i" modifier if already present', () => {
|
||||
os.platform.mockReturnValue('win32');
|
||||
const regex = createRegex('/test/i', true);
|
||||
os.platform.mockReturnValue("win32");
|
||||
const regex = createRegex("/test/i", true);
|
||||
expect(regex).toBeInstanceOf(RegExp);
|
||||
expect(regex.source).toBe('test');
|
||||
expect(regex.flags).toBe('i');
|
||||
expect(regex.source).toBe("test");
|
||||
expect(regex.flags).toBe("i");
|
||||
});
|
||||
|
||||
test('should handle escaped characters in the search string', () => {
|
||||
const regex = createRegex('/test\\/path/', false);
|
||||
test("should handle escaped characters in the search string", () => {
|
||||
const regex = createRegex("/test\\/path/", false);
|
||||
expect(regex).toBeInstanceOf(RegExp);
|
||||
expect(regex.source).toBe('test\\/path');
|
||||
expect(regex.flags).toBe('');
|
||||
expect(regex.source).toBe("test\\/path");
|
||||
expect(regex.flags).toBe("");
|
||||
});
|
||||
|
||||
test('should handle multiple modifiers', () => {
|
||||
const regex = createRegex('/test/gim', false);
|
||||
test("should handle multiple modifiers", () => {
|
||||
const regex = createRegex("/test/gim", false);
|
||||
expect(regex).toBeInstanceOf(RegExp);
|
||||
expect(regex.source).toBe('test');
|
||||
expect(regex.flags).toBe('gim');
|
||||
expect(regex.source).toBe("test");
|
||||
expect(regex.flags).toBe("gim");
|
||||
});
|
||||
|
||||
test('should handle empty search string', () => {
|
||||
const regex = createRegex('/^$/', false);
|
||||
test("should handle empty search string", () => {
|
||||
const regex = createRegex("/^$/", false);
|
||||
expect(regex).toBeInstanceOf(RegExp);
|
||||
expect(regex.source).toBe('^$');
|
||||
expect(regex.flags).toBe('');
|
||||
expect(regex.source).toBe("^$");
|
||||
expect(regex.flags).toBe("");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,60 +1,82 @@
|
|||
const ipMatch = require('../../src/utils/ipMatch');
|
||||
const ipMatch = require("../../src/utils/ipMatch");
|
||||
|
||||
describe('ipMatch', () => {
|
||||
test('should return true if IP1 is empty', () => {
|
||||
expect(ipMatch('', '192.168.1.1')).toBe(true);
|
||||
describe("ipMatch", () => {
|
||||
test("should return true if IP1 is empty", () => {
|
||||
expect(ipMatch("", "192.168.1.1")).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false if IP2 is empty', () => {
|
||||
expect(ipMatch('192.168.1.1', '')).toBe(false);
|
||||
test("should return false if IP2 is empty", () => {
|
||||
expect(ipMatch("192.168.1.1", "")).toBe(false);
|
||||
});
|
||||
|
||||
test('should return true if both IPs are empty', () => {
|
||||
expect(ipMatch('', '')).toBe(true);
|
||||
test("should return true if both IPs are empty", () => {
|
||||
expect(ipMatch("", "")).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true if both IPs are the same IPv4 address', () => {
|
||||
expect(ipMatch('192.168.1.1', '192.168.1.1')).toBe(true);
|
||||
test("should return true if both IPs are the same IPv4 address", () => {
|
||||
expect(ipMatch("192.168.1.1", "192.168.1.1")).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false if IPs are different IPv4 addresses', () => {
|
||||
expect(ipMatch('192.168.1.1', '192.168.1.2')).toBe(false);
|
||||
test("should return false if IPs are different IPv4 addresses", () => {
|
||||
expect(ipMatch("192.168.1.1", "192.168.1.2")).toBe(false);
|
||||
});
|
||||
|
||||
test('should normalize IPv4 addresses with leading zeros', () => {
|
||||
expect(ipMatch('192.168.001.001', '192.168.1.1')).toBe(true);
|
||||
test("should normalize IPv4 addresses with leading zeros", () => {
|
||||
expect(ipMatch("192.168.001.001", "192.168.1.1")).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true if both IPs are the same IPv6 address', () => {
|
||||
expect(ipMatch('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:db8:85a3::8a2e:370:7334')).toBe(true);
|
||||
test("should return true if both IPs are the same IPv6 address", () => {
|
||||
expect(
|
||||
ipMatch(
|
||||
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
|
||||
"2001:db8:85a3::8a2e:370:7334",
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false if IPs are different IPv6 addresses', () => {
|
||||
expect(ipMatch('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:db8:85a3::8a2e:370:7335')).toBe(false);
|
||||
test("should return false if IPs are different IPv6 addresses", () => {
|
||||
expect(
|
||||
ipMatch(
|
||||
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
|
||||
"2001:db8:85a3::8a2e:370:7335",
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('should expand IPv6 addresses with "::"', () => {
|
||||
expect(ipMatch('::1', '0:0:0:0:0:0:0:1')).toBe(true);
|
||||
expect(ipMatch("::1", "0:0:0:0:0:0:0:1")).toBe(true);
|
||||
});
|
||||
|
||||
test('should handle IPv6 addresses with embedded IPv4 addresses', () => {
|
||||
expect(ipMatch('::ffff:192.168.1.1', '192.168.1.1')).toBe(true);
|
||||
test("should handle IPv6 addresses with embedded IPv4 addresses", () => {
|
||||
expect(ipMatch("::ffff:192.168.1.1", "192.168.1.1")).toBe(true);
|
||||
});
|
||||
|
||||
test('should handle "localhost" as IPv6 loopback address', () => {
|
||||
expect(ipMatch('localhost', '::1')).toBe(true);
|
||||
expect(ipMatch("localhost", "::1")).toBe(true);
|
||||
});
|
||||
|
||||
test('should handle mixed case IP addresses', () => {
|
||||
expect(ipMatch('192.168.1.1', '192.168.1.1')).toBe(true);
|
||||
expect(ipMatch('2001:DB8:85A3::8A2E:370:7334', '2001:db8:85a3::8a2e:370:7334')).toBe(true);
|
||||
test("should handle mixed case IP addresses", () => {
|
||||
expect(ipMatch("192.168.1.1", "192.168.1.1")).toBe(true);
|
||||
expect(
|
||||
ipMatch("2001:DB8:85A3::8A2E:370:7334", "2001:db8:85a3::8a2e:370:7334"),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should handle IPv6 addresses with leading zeros', () => {
|
||||
expect(ipMatch('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:db8:85a3::8a2e:370:7334')).toBe(true);
|
||||
test("should handle IPv6 addresses with leading zeros", () => {
|
||||
expect(
|
||||
ipMatch(
|
||||
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
|
||||
"2001:db8:85a3::8a2e:370:7334",
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should handle IPv6 addresses with mixed case and leading zeros', () => {
|
||||
expect(ipMatch('2001:0DB8:85A3:0000:0000:8A2E:0370:7334', '2001:db8:85a3::8a2e:370:7334')).toBe(true);
|
||||
test("should handle IPv6 addresses with mixed case and leading zeros", () => {
|
||||
expect(
|
||||
ipMatch(
|
||||
"2001:0DB8:85A3:0000:0000:8A2E:0370:7334",
|
||||
"2001:db8:85a3::8a2e:370:7334",
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
Reference in a new issue