diff --git a/doc/api/hooks_server-side.md b/doc/api/hooks_server-side.md index 0bde2aad..51026140 100644 --- a/doc/api/hooks_server-side.md +++ b/doc/api/hooks_server-side.md @@ -247,3 +247,19 @@ Things in context: This hook will allow a plug-in developer to re-write each line when exporting to HTML. +## exportFileName +Called from src/node/handler/ExportHandler.js + +Things in context: + +1. padId + +This hook will allow a plug-in developer to modify the file name of an exported pad. This is useful if you want to export a pad under another name and/or hide the padId under export. Note that the doctype or file extension cannot be modified for security reasons. + +Example: + +``` +exports.exportFileName = function(hook, padId, callback){ + callback("newFileName"+padId); +} +``` diff --git a/src/node/handler/ExportHandler.js b/src/node/handler/ExportHandler.js index 8ff5bc48..a748d3f2 100644 --- a/src/node/handler/ExportHandler.js +++ b/src/node/handler/ExportHandler.js @@ -27,6 +27,7 @@ var async = require("async"); var fs = require("fs"); var settings = require('../utils/Settings'); var os = require('os'); +var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); //load abiword only if its enabled if(settings.abiword != null) @@ -45,175 +46,186 @@ if(os.type().indexOf("Windows") > -1) */ exports.doExport = function(req, res, padId, type) { - //tell the browser that this is a downloadable file - res.attachment(padId + "." + type); + var fileName = padId; - //if this is a plain text export, we can do this directly - // We have to over engineer this because tabs are stored as attributes and not plain text + // allow fileName to be overwritten by a hook, the type type is kept static for security reasons + hooks.aCallFirst("exportFileName", padId, + function(err, hookFileName){ + // if fileName is set then set it to the padId, note that fileName is returned as an array. + if(hookFileName) fileName = hookFileName; - if(type == "txt") - { - var txt; - var randNum; - var srcFile, destFile; - async.series([ - //render the txt document - function(callback) + //tell the browser that this is a downloadable file + res.attachment(fileName + "." + type); + + //if this is a plain text export, we can do this directly + // We have to over engineer this because tabs are stored as attributes and not plain text + + if(type == "txt") { - 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 + "/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([ + var txt; + var randNum; + var srcFile, destFile; + + async.series([ + //render the txt document function(callback) { - fs.unlink(srcFile, 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) { - //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) - { - if(err && err != "stop") ERR(err); - }) - } - else if(type == 'dokuwiki') - { - var randNum; - var srcFile, destFile; - - async.series([ - //render the dokuwiki document - function(callback) - { - exportdokuwiki.getPadDokuWikiDocument(padId, req.params.rev, function(err, dokuwiki) - { - res.send(dokuwiki); - callback("stop"); - }); - }, - ], function(err) - { - if(err && err != "stop") throw err; - }); - } - else - { - var html; - var randNum; - var srcFile, destFile; - - async.series([ - //render the html document - function(callback) - { - exporthtml.getPadHTMLDocument(padId, req.params.rev, false, function(err, _html) - { - if(ERR(err, callback)) return; - html = _html; - callback(); - }); - }, - //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"); - } - else //write the html export to a file - { - randNum = Math.floor(Math.random()*0xFFFFFFFF); - srcFile = tempDirectory + "/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 = tempDirectory + "/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); + //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) { - //100ms delay to accomidate for slow windows fs - if(os.type().indexOf("Windows") > -1) - { - setTimeout(function() + //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(destFile, callback); - }, 100); - } - else - { - fs.unlink(destFile, 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); } - ], callback); + ], function(err) + { + if(err && err != "stop") ERR(err); + }) } - ], function(err) - { - if(err && err != "stop") ERR(err); - }) - } + else if(type == 'dokuwiki') + { + var randNum; + var srcFile, destFile; + + async.series([ + //render the dokuwiki document + function(callback) + { + exportdokuwiki.getPadDokuWikiDocument(padId, req.params.rev, function(err, dokuwiki) + { + res.send(dokuwiki); + callback("stop"); + }); + }, + ], function(err) + { + if(err && err != "stop") throw err; + }); + } + else + { + var html; + var randNum; + var srcFile, destFile; + + async.series([ + //render the html document + function(callback) + { + exporthtml.getPadHTMLDocument(padId, req.params.rev, false, function(err, _html) + { + if(ERR(err, callback)) return; + html = _html; + callback(); + }); + }, + //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"); + } + else //write the html export to a file + { + randNum = Math.floor(Math.random()*0xFFFFFFFF); + srcFile = tempDirectory + "/etherpad_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 = 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) + { + if(err && err != "stop") ERR(err); + }) + } + } + ); }; diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index c2e46d1c..60fa5ffb 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -98,7 +98,7 @@ exports.doImport = function(req, res, padId) } }, function(callback){ - destFile = path.join(tmpDirectory, "eplite_import_" + randNum + ".htm"); + destFile = path.join(tmpDirectory, "etherpad_import_" + randNum + ".htm"); // Logic for allowing external Import Plugins hooks.aCallAll("import", {srcFile: srcFile, destFile: destFile}, function(err, result){