diff --git a/settings.json.template b/settings.json.template
index bfd0c7e6..321d21d6 100644
--- a/settings.json.template
+++ b/settings.json.template
@@ -86,10 +86,14 @@
may cause problems during deployment. Set to 0 to disable caching */
"maxAge" : 21600, // 60 * 60 * 6 = 6 hours
- /* This is the path to the Abiword executable. Setting it to null, disables abiword.
+ /* This is the absolute path to the Abiword executable. Setting it to null, disables abiword.
Abiword is needed to advanced import/export features of pads*/
"abiword" : null,
+ /* This is the absolute path to the soffice executable. Setting it to null, disables LibreOffice exporting.
+ LibreOffice can be used in lieu of Abiword to export pads */
+ "soffice" : null,
+
/* This is the path to the Tidy executable. Setting it to null, disables Tidy.
Tidy is used to improve the quality of exported pads*/
"tidyHtml" : null,
diff --git a/src/node/handler/ExportHandler.js b/src/node/handler/ExportHandler.js
index f861c82e..0a808977 100644
--- a/src/node/handler/ExportHandler.js
+++ b/src/node/handler/ExportHandler.js
@@ -30,9 +30,15 @@ var os = require('os');
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
var TidyHtml = require('../utils/TidyHtml');
+var convertor = null;
+
//load abiword only if its enabled
if(settings.abiword != null)
- var abiword = require("../utils/Abiword");
+ convertor = require("../utils/Abiword");
+
+// Use LibreOffice if an executable has been defined in the settings
+if(settings.soffice != null)
+ convertor = require("../utils/LibreOffice");
var tempDirectory = "/tmp";
@@ -70,71 +76,11 @@ exports.doExport = function(req, res, padId, type)
}
else if(type == "txt")
{
- var txt;
- var randNum;
- var srcFile, destFile;
-
- async.series([
- //render the txt document
- function(callback)
- {
- exporttxt.getPadTXTDocument(padId, req.params.rev, false, function(err, _txt)
- {
- if(ERR(err, callback)) return;
- txt = _txt;
- callback();
- });
- },
- //decide what to do with the txt export
- function(callback)
- {
- //if this is a txt export, we can send this from here directly
- res.send(txt);
- callback("stop");
- },
- //send the convert job to abiword
- function(callback)
- {
- //ensure html can be collected by the garbage collector
- txt = null;
-
- destFile = tempDirectory + "/etherpad_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)
- {
- //100ms delay to accomidate for slow windows fs
- if(os.type().indexOf("Windows") > -1)
- {
- setTimeout(function()
- {
- fs.unlink(destFile, callback);
- }, 100);
- }
- else
- {
- fs.unlink(destFile, callback);
- }
- }
- ], callback);
- }
- ], function(err)
+ exporttxt.getPadTXTDocument(padId, req.params.rev, false, function(err, txt)
{
- if(err && err != "stop") ERR(err);
- })
+ if(ERR(err)) return;
+ res.send(txt);
+ });
}
else
{
@@ -183,11 +129,11 @@ exports.doExport = function(req, res, padId, type)
TidyHtml.tidy(srcFile, callback);
},
- //send the convert job to abiword
+ //send the convert job to the convertor (abiword, libreoffice, ..)
function(callback)
{
destFile = tempDirectory + "/etherpad_export_" + randNum + "." + type;
- abiword.convertFile(srcFile, destFile, type, callback);
+ convertor.convertFile(srcFile, destFile, type, callback);
},
//send the file
function(callback)
diff --git a/src/node/utils/ExportHtml.js b/src/node/utils/ExportHtml.js
index 53469c9b..ffc7bc58 100644
--- a/src/node/utils/ExportHtml.js
+++ b/src/node/utils/ExportHtml.js
@@ -123,8 +123,8 @@ function getHTMLFromAtext(pad, atext, authorColors)
var newLength = props.push(propName);
anumMap[a] = newLength -1;
- css+=".removed {text-decoration: line-through; " +
- "-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)'; "+
+ css+=".removed {text-decoration: line-through; " +
+ "-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)'; "+
"filter: alpha(opacity=80); "+
"opacity: 0.8; "+
"}\n";
@@ -287,7 +287,7 @@ function getHTMLFromAtext(pad, atext, authorColors)
var s = taker.take(chars);
- //removes the characters with the code 12. Don't know where they come
+ //removes the characters with the code 12. Don't know where they come
//from but they break the abiword parser and are completly useless
s = s.replace(String.fromCharCode(12), "");
@@ -401,7 +401,7 @@ function getHTMLFromAtext(pad, atext, authorColors)
pieces.push('
');
}
}*/
- else//means we are getting closer to the lowest level of indentation or are at the same level
+ else//means we are getting closer to the lowest level of indentation or are at the same level
{
var toClose = lists.length > 0 ? listLevels[listLevels.length - 2] - line.listLevel : 0
if( toClose > 0){
@@ -455,7 +455,7 @@ function getHTMLFromAtext(pad, atext, authorColors)
}
}
}
-
+
for (var k = lists.length - 1; k >= 0; k--)
{
if(lists[k][1] == "number")
@@ -484,14 +484,17 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
stylesForExportCSS += css;
});
// Core inclusion of head etc.
- var head =
- (noDocType ? '' : '\n') +
- '\n' + (noDocType ? '' : '