Merge branch 'master' of git://github.com/Pita/etherpad-lite
commit
d8e39e82d1
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* Controls the communication with the Abiword application
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2011 Peter 'Pita' Martischka
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var util = require('util');
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
|
var async = require("async");
|
||||||
|
var settings = require("./settings");
|
||||||
|
|
||||||
|
//Queue with the converts we have to do
|
||||||
|
var queue = async.queue(doConvertTask, 1);
|
||||||
|
|
||||||
|
//spawn the abiword process
|
||||||
|
var abiword = spawn(settings.abiword, ["--plugin", "AbiCommand"]);
|
||||||
|
|
||||||
|
//output error messages to stderr
|
||||||
|
abiword.stderr.on('data', function (data)
|
||||||
|
{
|
||||||
|
console.error("Abiword: " + data);
|
||||||
|
});
|
||||||
|
|
||||||
|
//throw exceptions if abiword is dieing
|
||||||
|
abiword.on('exit', function (code)
|
||||||
|
{
|
||||||
|
throw "Abiword died with exit code " + code;
|
||||||
|
});
|
||||||
|
|
||||||
|
//delegate the processing of stdout to a other function
|
||||||
|
abiword.stdout.on('data',onAbiwordStdout);
|
||||||
|
|
||||||
|
var stdoutCallback = null;
|
||||||
|
var stdoutBuffer = "";
|
||||||
|
var firstPrompt = true;
|
||||||
|
|
||||||
|
function onAbiwordStdout(data)
|
||||||
|
{
|
||||||
|
//add data to buffer
|
||||||
|
stdoutBuffer+=data.toString();
|
||||||
|
|
||||||
|
//we're searching for the prompt, cause this means everything we need is in the buffer
|
||||||
|
if(stdoutBuffer.search("AbiWord:>") != -1)
|
||||||
|
{
|
||||||
|
//filter the feedback message
|
||||||
|
var lines = stdoutBuffer.split("\n");
|
||||||
|
var err = lines [1] == "OK" ? null : lines[1];
|
||||||
|
|
||||||
|
//reset the buffer
|
||||||
|
stdoutBuffer = "";
|
||||||
|
|
||||||
|
//call the callback with the error message
|
||||||
|
//skip the first prompt
|
||||||
|
if(stdoutCallback != null && !firstPrompt)
|
||||||
|
{
|
||||||
|
stdoutCallback(err);
|
||||||
|
stdoutCallback = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
firstPrompt = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function doConvertTask(task, callback)
|
||||||
|
{
|
||||||
|
abiword.stdin.write("convert " + task.srcFile + " " + task.destFile + " " + task.type + "\n");
|
||||||
|
|
||||||
|
//create a callback that calls the task callback and the caller callback
|
||||||
|
stdoutCallback = function (err)
|
||||||
|
{
|
||||||
|
callback();
|
||||||
|
task.callback(err);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.convertFile = function(srcFile, destFile, type, callback)
|
||||||
|
{
|
||||||
|
queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback});
|
||||||
|
};
|
|
@ -0,0 +1,116 @@
|
||||||
|
/**
|
||||||
|
* Handles the export requests
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2011 Peter 'Pita' Martischka
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var exporthtml = require("./exporters/exporthtml");
|
||||||
|
var padManager = require("./PadManager");
|
||||||
|
var async = require("async");
|
||||||
|
var fs = require("fs");
|
||||||
|
var settings = require('./settings');
|
||||||
|
|
||||||
|
//load abiword only if its enabled
|
||||||
|
if(settings.abiword != null)
|
||||||
|
var abiword = require("./Abiword");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do a requested export
|
||||||
|
*/
|
||||||
|
exports.doExport = function(req, res, padId, type)
|
||||||
|
{
|
||||||
|
//tell the browser that this is a downloadable file
|
||||||
|
res.attachment(padId + "." + type);
|
||||||
|
|
||||||
|
//if this is a plain text export, we can do this directly
|
||||||
|
if(type == "txt")
|
||||||
|
{
|
||||||
|
padManager.getPad(padId, function(err, pad)
|
||||||
|
{
|
||||||
|
if(err)
|
||||||
|
throw err;
|
||||||
|
|
||||||
|
res.send(pad.text());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var html;
|
||||||
|
var randNum;
|
||||||
|
var srcFile, destFile;
|
||||||
|
|
||||||
|
async.series([
|
||||||
|
//render the html document
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
|
||||||
|
{
|
||||||
|
html = _html;
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//decide what to do with the html export
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
//if this is a html export, we can send this from here directly
|
||||||
|
if(type == "html")
|
||||||
|
{
|
||||||
|
res.send(html);
|
||||||
|
callback("stop");
|
||||||
|
}
|
||||||
|
//write the html export to a file
|
||||||
|
else
|
||||||
|
{
|
||||||
|
randNum = Math.floor(Math.random()*new Date().getTime());
|
||||||
|
srcFile = "/tmp/eplite_export_" + randNum + ".html";
|
||||||
|
fs.writeFile(srcFile, html, callback);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//send the convert job to abiword
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
//ensure html can be collected by the garbage collector
|
||||||
|
html = null;
|
||||||
|
|
||||||
|
destFile = "/tmp/eplite_export_" + randNum + "." + type;
|
||||||
|
abiword.convertFile(srcFile, destFile, type, callback);
|
||||||
|
},
|
||||||
|
//send the file
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
res.sendfile(destFile, null, callback);
|
||||||
|
},
|
||||||
|
//clean up temporary files
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
async.parallel([
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
fs.unlink(srcFile, callback);
|
||||||
|
},
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
fs.unlink(destFile, callback);
|
||||||
|
}
|
||||||
|
], callback);
|
||||||
|
}
|
||||||
|
], function(err)
|
||||||
|
{
|
||||||
|
if(err && err != "stop") throw err;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
|
@ -31,6 +31,7 @@ var async = require('async');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var minify = require('./minify');
|
var minify = require('./minify');
|
||||||
|
var exportHandler;
|
||||||
var exporthtml;
|
var exporthtml;
|
||||||
var readOnlyManager;
|
var readOnlyManager;
|
||||||
|
|
||||||
|
@ -68,6 +69,7 @@ async.waterfall([
|
||||||
//load modules that needs a initalized db
|
//load modules that needs a initalized db
|
||||||
readOnlyManager = require("./ReadOnlyManager");
|
readOnlyManager = require("./ReadOnlyManager");
|
||||||
exporthtml = require("./exporters/exporthtml");
|
exporthtml = require("./exporters/exporthtml");
|
||||||
|
exportHandler = require('./ExportHandler');
|
||||||
|
|
||||||
//set logging
|
//set logging
|
||||||
if(settings.logHTTP)
|
if(settings.logHTTP)
|
||||||
|
@ -191,6 +193,28 @@ async.waterfall([
|
||||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//serve timeslider.html under /p/$padname/timeslider
|
||||||
|
app.get('/p/:pad/export/:type', function(req, res, next)
|
||||||
|
{
|
||||||
|
var types = ["pdf", "doc", "txt", "html", "odt"];
|
||||||
|
//send a 404 if we don't support this filetype
|
||||||
|
if(types.indexOf(req.params.type) == -1)
|
||||||
|
{
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if abiword is disabled, and this is a format we only support with abiword, output a message
|
||||||
|
if(settings.abiword == null && req.params.type != "html" && req.params.type != "txt" )
|
||||||
|
{
|
||||||
|
res.send("Abiword is not enabled at this Etherpad Lite instance. Set the path to Abiword in settings.json to enable this feature");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.header("Server", serverName);
|
||||||
|
exportHandler.doExport(req, res, req.params.pad, req.params.type);
|
||||||
|
});
|
||||||
|
|
||||||
//serve index.html under /
|
//serve index.html under /
|
||||||
app.get('/', function(req, res)
|
app.get('/', function(req, res)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,6 +46,11 @@ exports.defaultPadText = "Welcome to Etherpad Lite!\n\nThis pad text is synchron
|
||||||
*/
|
*/
|
||||||
exports.minify = true;
|
exports.minify = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the abiword executable
|
||||||
|
*/
|
||||||
|
exports.abiword = null;
|
||||||
|
|
||||||
//read the settings sync
|
//read the settings sync
|
||||||
var settingsStr = fs.readFileSync("../settings.json").toString();
|
var settingsStr = fs.readFileSync("../settings.json").toString();
|
||||||
|
|
||||||
|
@ -75,7 +80,7 @@ for(var i in settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
//we know this setting, so we overwrite it
|
//we know this setting, so we overwrite it
|
||||||
if(exports[i])
|
if(exports[i] !== undefined)
|
||||||
{
|
{
|
||||||
exports[i] = settings[i];
|
exports[i] = settings[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,5 +31,9 @@
|
||||||
|
|
||||||
/* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly,
|
/* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly,
|
||||||
but makes it impossible to debug the javascript/css */
|
but makes it impossible to debug the javascript/css */
|
||||||
"minify" : true
|
"minify" : true,
|
||||||
|
|
||||||
|
/* This is the path to the Abiword executable. Setting it to null, disables abiword.
|
||||||
|
Abiword is needed to enable the import/export of pads*/
|
||||||
|
"abiword" : null
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue