mirror of
				https://github.com/ether/etherpad-lite.git
				synced 2025-11-04 10:11:33 +01:00 
			
		
		
		
	Merge pull request #2150 from ether/export-file-name-hook
Server side hook to modify the export file name
This commit is contained in:
		
						commit
						44cb676ba2
					
				@ -247,3 +247,19 @@ Things in context:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
This hook will allow a plug-in developer to re-write each line when exporting to HTML.
 | 
					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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,7 @@ var async = require("async");
 | 
				
			|||||||
var fs = require("fs");
 | 
					var fs = require("fs");
 | 
				
			||||||
var settings = require('../utils/Settings');
 | 
					var settings = require('../utils/Settings');
 | 
				
			||||||
var os = require('os');
 | 
					var os = require('os');
 | 
				
			||||||
 | 
					var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//load abiword only if its enabled
 | 
					//load abiword only if its enabled
 | 
				
			||||||
if(settings.abiword != null)
 | 
					if(settings.abiword != null)
 | 
				
			||||||
@ -45,175 +46,186 @@ if(os.type().indexOf("Windows") > -1)
 | 
				
			|||||||
 */ 
 | 
					 */ 
 | 
				
			||||||
exports.doExport = function(req, res, padId, type)
 | 
					exports.doExport = function(req, res, padId, type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  //tell the browser that this is a downloadable file
 | 
					  var fileName = padId;
 | 
				
			||||||
  res.attachment(padId + "." + type);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //if this is a plain text export, we can do this directly
 | 
					  // allow fileName to be overwritten by a hook, the type type is kept static for security reasons
 | 
				
			||||||
  // We have to over engineer this because tabs are stored as attributes and not plain text
 | 
					  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([
 | 
					      //tell the browser that this is a downloadable file
 | 
				
			||||||
      //render the txt document
 | 
					      res.attachment(fileName + "." + type);
 | 
				
			||||||
      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 + "/eplite_export_" + randNum + "." + type;
 | 
					      //if this is a plain text export, we can do this directly
 | 
				
			||||||
        abiword.convertFile(srcFile, destFile, type, callback);
 | 
					      // We have to over engineer this because tabs are stored as attributes and not plain text
 | 
				
			||||||
      },
 | 
					    
 | 
				
			||||||
      //send the file
 | 
					      if(type == "txt")
 | 
				
			||||||
      function(callback)
 | 
					 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        res.sendfile(destFile, null, callback);
 | 
					        var txt;
 | 
				
			||||||
      },
 | 
					        var randNum;
 | 
				
			||||||
      //clean up temporary files
 | 
					        var srcFile, destFile;
 | 
				
			||||||
      function(callback)
 | 
					    
 | 
				
			||||||
      {
 | 
					        async.series([
 | 
				
			||||||
        async.parallel([
 | 
					          //render the txt document
 | 
				
			||||||
          function(callback)
 | 
					          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)
 | 
					          function(callback)
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            //100ms delay to accomidate for slow windows fs
 | 
					            //if this is a txt export, we can send this from here directly
 | 
				
			||||||
            if(os.type().indexOf("Windows") > -1)
 | 
					            res.send(txt);
 | 
				
			||||||
            {
 | 
					            callback("stop");
 | 
				
			||||||
              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);
 | 
					 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
 | 
					          //send the convert job to abiword
 | 
				
			||||||
          function(callback)
 | 
					          function(callback)
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            //100ms delay to accomidate for slow windows fs
 | 
					            //ensure html can be collected by the garbage collector
 | 
				
			||||||
            if(os.type().indexOf("Windows") > -1)
 | 
					            txt = null;
 | 
				
			||||||
            {
 | 
					    
 | 
				
			||||||
              setTimeout(function() 
 | 
					            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);
 | 
					                fs.unlink(srcFile, callback);
 | 
				
			||||||
              }, 100);
 | 
					              },
 | 
				
			||||||
            }
 | 
					              function(callback)
 | 
				
			||||||
            else
 | 
					              {
 | 
				
			||||||
            {
 | 
					                //100ms delay to accomidate for slow windows fs
 | 
				
			||||||
              fs.unlink(destFile, callback);
 | 
					                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)
 | 
					      else if(type == 'dokuwiki')
 | 
				
			||||||
    {
 | 
					      {
 | 
				
			||||||
      if(err && err != "stop") ERR(err);
 | 
					        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);
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -98,7 +98,7 @@ exports.doImport = function(req, res, padId)
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    function(callback){
 | 
					    function(callback){
 | 
				
			||||||
      destFile = path.join(tmpDirectory, "eplite_import_" + randNum + ".htm");
 | 
					      destFile = path.join(tmpDirectory, "etherpad_import_" + randNum + ".htm");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Logic for allowing external Import Plugins
 | 
					      // Logic for allowing external Import Plugins
 | 
				
			||||||
      hooks.aCallAll("import", {srcFile: srcFile, destFile: destFile}, function(err, result){
 | 
					      hooks.aCallAll("import", {srcFile: srcFile, destFile: destFile}, function(err, result){
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user