diff --git a/README.md b/README.md
index 6e8174d..1cd0532 100644
--- a/README.md
+++ b/README.md
@@ -266,6 +266,10 @@ There will always be more work to do here. ;-)
### Updates
+#### v0.7.9 11/8/17 by DW
+
+A new top-level config.json option, `flUnicasePaths`. The feature is documented.
+
#### v0.7.8 10/3/17 by DW
New features supports logging over WebSockets. To enable, in config.json set flWebsocketEnabled true, and assign a port to the WS server in websocketPort. On every hit, PagePark will send back a JSON structure containing information about the request.
diff --git a/docs/config.md b/docs/config.md
index d913c9b..8490d19 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -64,3 +64,9 @@ Example:
{"flProcessScriptFiles": false}
+#### Case-sensitive paths
+
+If the filesystem on the server is case sensitive, as Ubuntu is, and you're porting a site from another system where file names are not case-sensitive, you will need to set `flUnicasePaths` to true. By default it's false.
+
+This option was added in v0.7.9.
+
diff --git a/package.json b/package.json
index 519243f..a144bfe 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "PagePark",
"description": "A simple Node.js folder-based HTTP server that serves static and dynamic pages for domains.",
"author": "Dave Winer ",
- "version": "0.7.8",
+ "version": "0.7.9",
"scripts": {
"start": "node pagepark.js"
},
diff --git a/pagepark.js b/pagepark.js
index 6a49e39..e81b81c 100644
--- a/pagepark.js
+++ b/pagepark.js
@@ -1,4 +1,4 @@
-var myVersion = "0.7.8", myProductName = "PagePark";
+var myVersion = "0.7.9", myProductName = "PagePark";
/* The MIT License (MIT)
Copyright (c) 2014-2017 Dave Winer
@@ -47,7 +47,8 @@ var pageparkPrefs = {
flCacheTemplatesLocally: true, //6/17/17 by DW -- preserve the original behavior
urlDefaultMarkdownTemplate: "http://fargo.io/code/pagepark/defaultmarkdowntemplate.txt", //6/17/17 by DW
urlDefaultOpmlTemplate: "http://fargo.io/code/pagepark/templates/opml/template.txt", //6/17/17 by DW
- urlDefaultErrorPage: "http://fargo.io/code/pagepark/prefs/error.html" //6/17/17 by DW
+ urlDefaultErrorPage: "http://fargo.io/code/pagepark/prefs/error.html", //6/17/17 by DW
+ flUnicasePaths: false //11/7/17 by DW
};
var pageparkStats = {
ctStarts: 0,
@@ -451,6 +452,60 @@ function handleHttpRequest (httpRequest, httpResponse) {
}
callback (undefined); //it's one of our domains, handle it here
}
+ function pathParse (domainfolder, path, callback) { //11/7/17 by DW
+ if (pageparkPrefs.flUnicasePaths) {
+ var nomad = domainfolder, steps, flSlashAtEnd = false;
+ if (utils.beginsWith (path, "/")) {
+ path = utils.stringDelete (path, 1, 1);
+ }
+ steps = path.split ("/");
+
+ if (steps [steps.length - 1].length == 0) {
+ steps.pop ();
+ flSlashAtEnd = true;
+ }
+
+ function doStep (ix) {
+ if (ix < steps.length) {
+ var lowerstep = utils.stringLower (steps [ix]), flfound = false;
+ if (!utils.endsWith (nomad, "/")) {
+ nomad += "/";
+ }
+ fs.readdir (nomad, function (err, list) {
+ if (err) {
+ callback (err);
+ }
+ else {
+ for (var i = 0; i < list.length; i++) {
+ var fname = utils.stringLower (list [i]);
+ if (fname == lowerstep) {
+ nomad += list [i];
+ doStep (ix + 1);
+ flfound = true;
+ break;
+ }
+ }
+ if (!flfound) {
+ var err = {
+ };
+ callback (err);
+ }
+ }
+ });
+ }
+ else {
+ if (flSlashAtEnd) {
+ nomad += "/";
+ }
+ callback (undefined, nomad);
+ }
+ }
+ doStep (0);
+ }
+ else {
+ callback (undefined, domainfolder + path);
+ }
+ }
try {
var parsedUrl = urlpack.parse (httpRequest.url, true), host, lowerhost, port, referrer;
@@ -533,116 +588,120 @@ function handleHttpRequest (httpRequest, httpResponse) {
}
else { //no mapping, we handle the request
getDomainFolder (host, function (domainfolder, actualhost) { //might be a wildcard folder
- var f = domainfolder + parsedUrl.pathname;
- if (checkPathForIllegalChars (f)) {
- utils.sureFilePath (domainsPath, function () { //make sure domains folder exists
- getConfigFile (actualhost, function (config) { //get config.json, if it exists -- 1/18/15 by DW
- if (config != undefined) {
- if (config.jsSiteRedirect != undefined) { //7/7/15 by DW
- try {
- var urlRedirect = eval (config.jsSiteRedirect.toString ());
+ pathParse (domainfolder, parsedUrl.pathname, function (err, f) {
+ if (f === undefined) {
+ f = domainfolder + parsedUrl.pathname;
+ }
+ if (checkPathForIllegalChars (f)) {
+ utils.sureFilePath (domainsPath, function () { //make sure domains folder exists
+ getConfigFile (actualhost, function (config) { //get config.json, if it exists -- 1/18/15 by DW
+ if (config != undefined) {
+ if (config.jsSiteRedirect != undefined) { //7/7/15 by DW
+ try {
+ var urlRedirect = eval (config.jsSiteRedirect.toString ());
+ returnRedirect (urlRedirect.toString (), false); //9/30/17 by DW
+ }
+ catch (err) {
+ httpRespond (500, "text/plain", "Error running " + config.jsSiteRedirect + ": \"" + err.message + "\"");
+ }
+ return;
+ }
+ if (config.urlSiteRedirect != undefined) {
+ var urlRedirect = config.urlSiteRedirect + parsedUrl.pathname;
returnRedirect (urlRedirect.toString (), false); //9/30/17 by DW
+ return;
}
- catch (err) {
- httpRespond (500, "text/plain", "Error running " + config.jsSiteRedirect + ": \"" + err.message + "\"");
+ if (config.urlSiteContents != undefined) { //4/26/15 by DW -- v0.55
+ delegateRequest (config.urlSiteContents + httpRequest.url);
+ return;
}
- return;
- }
- if (config.urlSiteRedirect != undefined) {
- var urlRedirect = config.urlSiteRedirect + parsedUrl.pathname;
- returnRedirect (urlRedirect.toString (), false); //9/30/17 by DW
- return;
- }
- if (config.urlSiteContents != undefined) { //4/26/15 by DW -- v0.55
- delegateRequest (config.urlSiteContents + httpRequest.url);
- return;
- }
- if (config.fargoS3Path != undefined) { //5/11/15 PM by DW v0.58
- var firstPartOfHost = utils.stringNthField (host, ".", 1); //if it's dave.smallpict.com, this value is "dave"
- var s3url = "http:/" + config.fargoS3Path + firstPartOfHost + parsedUrl.pathname; //xxx
- request (s3url, function (error, response, body) {
- if (error) {
- httpRespond (500, "text/plain", "Error accessing S3 data: " + error.message);
- }
- else {
- httpRespond (response.statusCode, response.headers ["content-type"], body);
- }
- });
- return;
- }
- if (config.s3Path != undefined) { //9/26/17 by DW
- var s3url = "http:/" + config.s3Path + parsedUrl.pathname;
- request (s3url, function (error, response, body) {
- if (error) {
- httpRespond (500, "text/plain", "Error accessing S3 data: " + error.message);
- }
- else {
- if (response.statusCode == 200) {
- processResponse (parsedUrl.pathname, body, config, function (code, type, text) {
- httpRespond (code, type, text);
- });
+ if (config.fargoS3Path != undefined) { //5/11/15 PM by DW v0.58
+ var firstPartOfHost = utils.stringNthField (host, ".", 1); //if it's dave.smallpict.com, this value is "dave"
+ var s3url = "http:/" + config.fargoS3Path + firstPartOfHost + parsedUrl.pathname; //xxx
+ request (s3url, function (error, response, body) {
+ if (error) {
+ httpRespond (500, "text/plain", "Error accessing S3 data: " + error.message);
}
else {
httpRespond (response.statusCode, response.headers ["content-type"], body);
}
- }
- });
- return;
- }
- if (config.localPath != undefined) { //9/26/17 by DW
- var localFile = config.localPath + parsedUrl.pathname;
- console.log ("localFile == " + localFile);
- serveFile (localFile, config);
- return;
- }
- }
- fs.stat (f, function (err, stats) {
- if (err) {
- switch (lowerpath) {
- case "/version":
- httpRespond (200, "text/plain", myVersion);
- break;
- case "/now":
- httpRespond (200, "text/plain", now.toString ());
- break;
- case "/status":
- var status = {
- prefs: pageparkPrefs,
- status: pageparkStats
+ });
+ return;
+ }
+ if (config.s3Path != undefined) { //9/26/17 by DW
+ var s3url = "http:/" + config.s3Path + parsedUrl.pathname;
+ request (s3url, function (error, response, body) {
+ if (error) {
+ httpRespond (500, "text/plain", "Error accessing S3 data: " + error.message);
}
- httpRespond (200, "text/plain", utils.jsonStringify (status));
- break;
- default:
- if (!serveRedirect (lowerpath, config)) { //12/8/15 by DW -- it wasn't a redirect
- return404 ();
+ else {
+ if (response.statusCode == 200) {
+ processResponse (parsedUrl.pathname, body, config, function (code, type, text) {
+ httpRespond (code, type, text);
+ });
+ }
+ else {
+ httpRespond (response.statusCode, response.headers ["content-type"], body);
+ }
}
- break;
+ });
+ return;
+ }
+ if (config.localPath != undefined) { //9/26/17 by DW
+ var localFile = config.localPath + parsedUrl.pathname;
+ console.log ("localFile == " + localFile);
+ serveFile (localFile, config);
+ return;
}
}
- else {
- if (!serveRedirect (lowerpath, config)) { //7/30/15 by DW -- it wasn't a redirect
- if (stats.isDirectory ()) {
- if (!utils.endsWith (f, "/")) {
- returnRedirect (httpRequest.url + "/", false); //7/5/17 by DW
+ fs.stat (f, function (err, stats) {
+ if (err) {
+ switch (lowerpath) {
+ case "/version":
+ httpRespond (200, "text/plain", myVersion);
+ break;
+ case "/now":
+ httpRespond (200, "text/plain", now.toString ());
+ break;
+ case "/status":
+ var status = {
+ prefs: pageparkPrefs,
+ status: pageparkStats
+ }
+ httpRespond (200, "text/plain", utils.jsonStringify (status));
+ break;
+ default:
+ if (!serveRedirect (lowerpath, config)) { //12/8/15 by DW -- it wasn't a redirect
+ return404 ();
+ }
+ break;
+ }
+ }
+ else {
+ if (!serveRedirect (lowerpath, config)) { //7/30/15 by DW -- it wasn't a redirect
+ if (stats.isDirectory ()) {
+ if (!utils.endsWith (f, "/")) {
+ returnRedirect (httpRequest.url + "/", false); //7/5/17 by DW
+ }
+ else {
+ findSpecificFile (f, pageparkPrefs.indexFilename, function (findex) {
+ serveFile (findex, config);
+ });
+ }
}
else {
- findSpecificFile (f, pageparkPrefs.indexFilename, function (findex) {
- serveFile (findex, config);
- });
+ serveFile (f, config);
}
}
- else {
- serveFile (f, config);
- }
}
- }
+ });
});
});
- });
- }
- else {
- httpRespond (500, "text/plain", "The file name contains illegal characters.");
- }
+ }
+ else {
+ httpRespond (400, "text/plain", "The file name contains illegal characters.");
+ }
+ });
});
}
});