node-webodf
Version:
WebODF - JavaScript Document Engine http://webodf.org/
227 lines (218 loc) • 9.24 kB
JavaScript
/**
* Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
*
* @licstart
* This file is part of WebODF.
*
* WebODF is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License (GNU AGPL)
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* WebODF is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with WebODF. If not, see <http://www.gnu.org/licenses/>.
* @licend
*
* @source: http://www.webodf.org/
* @source: https://github.com/kogmbh/WebODF/
*/
/*global require, console, process, Buffer, unescape*/
/* A Node.JS http server*/
var http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs"),
lookForIndexHtml = true,
ipaddress = "127.0.0.1",
port = 8124;
function statFile(dir, filelist, position, callback) {
"use strict";
if (position >= filelist.length) {
return callback(null, filelist);
}
fs.stat(dir + "/" + filelist[position], function (err, stats) {
if (stats && stats.isDirectory()) {
filelist[position] = filelist[position] + "/";
}
statFile(dir, filelist, position + 1, callback);
});
}
function listFiles(dir, callback) {
"use strict";
fs.readdir(dir, function (err, files) {
if (err) {
return callback(err);
}
statFile(dir, files, 0, callback);
});
}
http.createServer(function (request, response) {
"use strict";
var uri = unescape(url.parse(request.url).pathname),
filename = path.join(process.cwd(), uri);
if (uri !== '/favicon.ico') {
console.log(request.method + " " + uri);
}
function put() {
var contentlength = parseInt(request.headers["content-length"], 10),
alldata = new Buffer(contentlength),
sum = 0;
request.on("data", function (data) {
data.copy(alldata, sum, 0);
sum += data.length;
});
request.on("end", function () {
fs.writeFile(filename, alldata, "binary", function (err) {
if (err) {
response.writeHead(500);
response.write(err);
} else {
response.writeHead(200);
}
response.end();
});
});
}
if (request.method === "PUT") {
put(request, response);
return;
}
if (request.method === "DELETE") {
fs.unlink(filename, function (err) {
if (err) {
response.writeHead(500);
} else {
response.writeHead(200);
}
response.end();
});
return;
}
function setContentTypeInHead(head, filename) {
var contentTypeLookupTable = [
{ext: [".js"], type: "text/javascript"},
{ext: [".css"], type: "text/css"},
{ext: [".odt"], type: "application/vnd.oasis.opendocument.text"},
{ext: [".fodt"], type: "application/vnd.oasis.opendocument.text-flat-xml"},
{ext: [".ott"], type: "application/vnd.oasis.opendocument.text-template"},
{ext: [".odp"], type: "application/vnd.oasis.opendocument.presentation"},
{ext: [".fodp"], type: "application/vnd.oasis.opendocument.presentation-flat-xml"},
{ext: [".otp"], type: "application/vnd.oasis.opendocument.presentation-template"},
{ext: [".ods"], type: "application/vnd.oasis.opendocument.spreadsheet"},
{ext: [".fods"], type: "application/vnd.oasis.opendocument.spreadsheet-flat-xml"},
{ext: [".ots"], type: "application/vnd.oasis.opendocument.spreadsheet-template"},
{ext: [".json"], type: "application/json"},
{ext: [".txt"], type: "text/plain; charset=utf-8"},
{ext: [".html"], type: "text/html; charset=utf-8"},
{ext: [".xhtml"], type: "application/xhtml+xml; charset=utf-8"},
{ext: [".xml"], type: "text/xml; charset=utf-8"},
{ext: [".ttf"], type: "application/x-font-ttf"},
{ext: [".jpg",".jpeg"], type: "image/jpeg"},
{ext: [".gif"], type: "image/gif"},
{ext: [".png"], type: "image/png"}
];
contentTypeLookupTable.some(function (contentTypeEntry) {
return contentTypeEntry.ext.some(function (ext) {
if (filename.substr(-ext.length) === ext) {
head["Content-Type"] = contentTypeEntry.type;
return true;
}
return false;
});
});
}
function handleStat(err, stats, lookForIndexHtml) {
if (!err && stats.isFile()) {
fs.readFile(filename, "binary", function (err, file) {
if (err) {
response.writeHead(500, {"Content-Type": "text/plain"});
if (request.method !== "HEAD") {
response.write(err + "\n");
}
response.end();
return;
}
var head = {"Content-Length": stats.size};
setContentTypeInHead(head, filename);
response.writeHead(200, head);
if (request.method !== "HEAD") {
response.write(file, "binary");
}
response.end();
});
} else if (!err && stats.isDirectory()) {
if (lookForIndexHtml) {
fs.stat(filename + "/index.html", function (err, stats) {
if (err) {
fs.stat(filename, handleStat);
} else {
filename = filename + "/index.html";
handleStat(err, stats);
}
});
return;
}
if (uri.length === 0 || uri[uri.length - 1] !== "/") {
response.writeHead(301, {"Content-Type": "text/plain",
"Location": uri + "/"});
if (request.method !== "HEAD") {
response.write("Moved permanently\n");
}
response.end();
return;
}
listFiles(filename, function (err, files) {
if (err) {
response.writeHead(500, {"Content-Type": "text/plain"});
if (request.method !== "HEAD") {
response.write(err + "\n");
}
response.end();
return;
}
response.writeHead(200);
if (request.method !== "HEAD") {
files.sort();
response.write("<html><head><title></title></head><body>");
response.write("<table>");
var i, l = files.length, file;
for (i = 0; i < l; i += 1) {
file = files[i];
if (file.length > 0 && file[file.length - 1] === '/') {
file = encodeURIComponent(file.slice(0, file.length - 1)) + "/";
} else {
file = encodeURIComponent(file);
}
response.write("<tr><td><a href=\"");
response.write(file);
response.write("\">");
file = files[i].replace("&", "&")
.replace("<", ">");
response.write(file.replace("\"", "\\\""));
response.write("</a></td></tr>\n");
}
response.write("</table></body></html>\n");
}
response.end();
});
} else {
if (uri !== '/favicon.ico') {
console.log("Not found: " + uri);
}
response.writeHead(404, {"Content-Type": "text/plain"});
if (request.method !== "HEAD") {
response.write("404 Not Found\n");
}
response.end();
}
}
fs.stat(filename, function (err, stats) {
handleStat(err, stats, lookForIndexHtml);
});
}).listen(port, ipaddress);
console.log('Server running at http://' + ipaddress + ':' + port + '/');