forked from svrjs/svrjs
Prepare for double slash URL support
This commit is contained in:
parent
bd5ab63954
commit
28d633884e
1 changed files with 19 additions and 12 deletions
31
svr.js
31
svr.js
|
@ -3328,17 +3328,19 @@ if (!cluster.isPrimary) {
|
||||||
|
|
||||||
// Function to parse a URL string into a URL object
|
// Function to parse a URL string into a URL object
|
||||||
function parseURL(uri) {
|
function parseURL(uri) {
|
||||||
|
// Prepare the path (remove multiple slashes)
|
||||||
|
var preparedURI = uri.replace(/^\/{2,}/,"/");
|
||||||
// Check if the URL API is available (Node.js version >= 10)
|
// Check if the URL API is available (Node.js version >= 10)
|
||||||
if (typeof URL !== "undefined" && url.Url) {
|
if (typeof URL !== "undefined" && url.Url) {
|
||||||
try {
|
try {
|
||||||
// Create a new URL object using the provided URI and base URL
|
// Create a new URL object using the provided URI and base URL
|
||||||
var uobject = new URL(uri.replace(/^\/{2,}/,"/"), "http" + (req.socket.encrypted ? "s" : "") + "://" + (req.headers.host ? req.headers.host : (domain ? domain : "unknown.invalid")));
|
var uobject = new URL(preparedURI, "http" + (req.socket.encrypted ? "s" : "") + "://" + (req.headers.host ? req.headers.host : (domain ? domain : "unknown.invalid")));
|
||||||
|
|
||||||
// Create a new URL object (similar to deprecated url.Url)
|
// Create a new URL object (similar to deprecated url.Url)
|
||||||
var nuobject = new url.Url();
|
var nuobject = new url.Url();
|
||||||
|
|
||||||
// Set properties of the new URL object from the provided URL
|
// Set properties of the new URL object from the provided URL
|
||||||
if (uri.indexOf("/") != -1) nuobject.slashes = true;
|
if (preparedURI.indexOf("/") != -1) nuobject.slashes = true;
|
||||||
if (uobject.protocol != "") nuobject.protocol = uobject.protocol;
|
if (uobject.protocol != "") nuobject.protocol = uobject.protocol;
|
||||||
if (uobject.username != "" && uobject.password != "") nuobject.auth = uobject.username + ":" + uobject.password;
|
if (uobject.username != "" && uobject.password != "") nuobject.auth = uobject.username + ":" + uobject.password;
|
||||||
if (uobject.host != "") nuobject.host = uobject.host;
|
if (uobject.host != "") nuobject.host = uobject.host;
|
||||||
|
@ -3350,7 +3352,7 @@ if (!cluster.isPrimary) {
|
||||||
if (uobject.href != "") nuobject.href = uobject.href;
|
if (uobject.href != "") nuobject.href = uobject.href;
|
||||||
|
|
||||||
// Adjust the pathname and href properties if the URI doesn't start with "/"
|
// Adjust the pathname and href properties if the URI doesn't start with "/"
|
||||||
if (uri.indexOf("/") != 0) {
|
if (preparedURI.indexOf("/") != 0) {
|
||||||
if (nuobject.pathname) {
|
if (nuobject.pathname) {
|
||||||
nuobject.pathname = nuobject.pathname.substr(1);
|
nuobject.pathname = nuobject.pathname.substr(1);
|
||||||
nuobject.href = nuobject.pathname + (nuobject.search ? nuobject.search : "");
|
nuobject.href = nuobject.pathname + (nuobject.search ? nuobject.search : "");
|
||||||
|
@ -3372,11 +3374,11 @@ if (!cluster.isPrimary) {
|
||||||
return nuobject;
|
return nuobject;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// If there was an error using the URL API, fall back to deprecated url.parse
|
// If there was an error using the URL API, fall back to deprecated url.parse
|
||||||
return url.parse(uri, true);
|
return url.parse(preparedURI, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the URL API is not available, fall back to deprecated url.parse
|
// If the URL API is not available, fall back to deprecated url.parse
|
||||||
return url.parse(uri, true);
|
return url.parse(preparedURI, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4313,6 +4315,7 @@ if (!cluster.isPrimary) {
|
||||||
doCallback = false;
|
doCallback = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!mapEntry.allowDoubleSlashes) address = address.replace(/\/+/g,"/");
|
||||||
if (matchHostname(mapEntry.host) && ipMatch(mapEntry.ip, req.socket ? req.socket.localAddress : undefined) && address.match(createRegex(mapEntry.definingRegex)) && !(mapEntry.isNotDirectory && _fileState == 2) && !(mapEntry.isNotFile && _fileState == 1)) {
|
if (matchHostname(mapEntry.host) && ipMatch(mapEntry.ip, req.socket ? req.socket.localAddress : undefined) && address.match(createRegex(mapEntry.definingRegex)) && !(mapEntry.isNotDirectory && _fileState == 2) && !(mapEntry.isNotFile && _fileState == 1)) {
|
||||||
try {
|
try {
|
||||||
mapEntry.replacements.forEach(function (replacement) {
|
mapEntry.replacements.forEach(function (replacement) {
|
||||||
|
@ -4510,24 +4513,27 @@ if (!cluster.isPrimary) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare the path (remove multiple slashes)
|
||||||
|
var decodedHrefWithoutDuplicateSlashes = decodedHref.replace(/\/+/g,"/");
|
||||||
|
|
||||||
// Check if path is forbidden
|
// Check if path is forbidden
|
||||||
if ((isForbiddenPath(decodedHref, "config") || isForbiddenPath(decodedHref, "certificates")) && !isProxy) {
|
if ((isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "config") || isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "certificates")) && !isProxy) {
|
||||||
callServerError(403);
|
callServerError(403);
|
||||||
serverconsole.errmessage("Access to configuration file/certificates is denied.");
|
serverconsole.errmessage("Access to configuration file/certificates is denied.");
|
||||||
return;
|
return;
|
||||||
} else if (isIndexOfForbiddenPath(decodedHref, "temp") && !isProxy) {
|
} else if (isIndexOfForbiddenPath(decodedHrefWithoutDuplicateSlashes, "temp") && !isProxy) {
|
||||||
callServerError(403);
|
callServerError(403);
|
||||||
serverconsole.errmessage("Access to temporary folder is denied.");
|
serverconsole.errmessage("Access to temporary folder is denied.");
|
||||||
return;
|
return;
|
||||||
} else if (isIndexOfForbiddenPath(decodedHref, "log") && !isProxy && (configJSON.enableLogging || configJSON.enableLogging == undefined) && !configJSON.enableRemoteLogBrowsing) {
|
} else if (isIndexOfForbiddenPath(decodedHrefWithoutDuplicateSlashes, "log") && !isProxy && (configJSON.enableLogging || configJSON.enableLogging == undefined) && !configJSON.enableRemoteLogBrowsing) {
|
||||||
callServerError(403);
|
callServerError(403);
|
||||||
serverconsole.errmessage("Access to log files is denied.");
|
serverconsole.errmessage("Access to log files is denied.");
|
||||||
return;
|
return;
|
||||||
} else if (isForbiddenPath(decodedHref, "svrjs") && !isProxy && !exposeServerVersion) {
|
} else if (isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "svrjs") && !isProxy && !exposeServerVersion) {
|
||||||
callServerError(403);
|
callServerError(403);
|
||||||
serverconsole.errmessage("Access to SVR.JS script is denied.");
|
serverconsole.errmessage("Access to SVR.JS script is denied.");
|
||||||
return;
|
return;
|
||||||
} else if ((isForbiddenPath(decodedHref, "svrjs") || isForbiddenPath(decodedHref, "serverSideScripts") || isIndexOfForbiddenPath(decodedHref, "serverSideScriptDirectories")) && !isProxy && (configJSON.disableServerSideScriptExpose || configJSON.disableServerSideScriptExpose === undefined)) {
|
} else if ((isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "svrjs") || isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "serverSideScripts") || isIndexOfForbiddenPath(decodedHrefWithoutDuplicateSlashes, "serverSideScriptDirectories")) && !isProxy && (configJSON.disableServerSideScriptExpose || configJSON.disableServerSideScriptExpose === undefined)) {
|
||||||
callServerError(403);
|
callServerError(403);
|
||||||
serverconsole.errmessage("Access to sources is denied.");
|
serverconsole.errmessage("Access to sources is denied.");
|
||||||
return;
|
return;
|
||||||
|
@ -4541,14 +4547,15 @@ if (!cluster.isPrimary) {
|
||||||
for (var i = 0; i < nonStandardCodes.length; i++) {
|
for (var i = 0; i < nonStandardCodes.length; i++) {
|
||||||
if (matchHostname(nonStandardCodes[i].host) && ipMatch(nonStandardCodes[i].ip, req.socket ? req.socket.localAddress : undefined)) {
|
if (matchHostname(nonStandardCodes[i].host) && ipMatch(nonStandardCodes[i].ip, req.socket ? req.socket.localAddress : undefined)) {
|
||||||
var isMatch = false;
|
var isMatch = false;
|
||||||
|
var hrefWithoutDuplicateSlashes = href.replace(/\/+/g,"/");
|
||||||
if (nonStandardCodes[i].regex) {
|
if (nonStandardCodes[i].regex) {
|
||||||
// Regex match
|
// Regex match
|
||||||
var createdRegex = createRegex(nonStandardCodes[i].regex, true);
|
var createdRegex = createRegex(nonStandardCodes[i].regex, true);
|
||||||
isMatch = req.url.match(createdRegex) || href.match(createdRegex);
|
isMatch = req.url.match(createdRegex) || hrefWithoutDuplicateSlashes.match(createdRegex);
|
||||||
regexI[i] = createdRegex;
|
regexI[i] = createdRegex;
|
||||||
} else {
|
} else {
|
||||||
// Non-regex match
|
// Non-regex match
|
||||||
isMatch = nonStandardCodes[i].url == href || (os.platform() == "win32" && nonStandardCodes[i].url.toLowerCase() == href.toLowerCase());
|
isMatch = nonStandardCodes[i].url == hrefWithoutDuplicateSlashes || (os.platform() == "win32" && nonStandardCodes[i].url.toLowerCase() == hrefWithoutDuplicateSlashes.toLowerCase());
|
||||||
}
|
}
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
if (nonStandardCodes[i].scode == 401) {
|
if (nonStandardCodes[i].scode == 401) {
|
||||||
|
|
Reference in a new issue