Import works now on the server side
This commit is contained in:
parent
4b268f9579
commit
b13fbbfd73
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* Handles the import 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 padManager = require("./PadManager");
|
||||
var padMessageHandler = require("./PadMessageHandler");
|
||||
var async = require("async");
|
||||
var fs = require("fs");
|
||||
var settings = require('./settings');
|
||||
var formidable = require('formidable');
|
||||
|
||||
//load abiword only if its enabled
|
||||
if(settings.abiword != null)
|
||||
var abiword = require("./Abiword");
|
||||
|
||||
/**
|
||||
* do a requested import
|
||||
*/
|
||||
exports.doImport = function(req, res, padId)
|
||||
{
|
||||
//pipe to a file
|
||||
//convert file to text via abiword
|
||||
//set text in the pad
|
||||
|
||||
var srcFile, destFile;
|
||||
var pad;
|
||||
var text;
|
||||
|
||||
async.series([
|
||||
//save the uploaded file to /tmp
|
||||
function(callback)
|
||||
{
|
||||
var form = new formidable.IncomingForm();
|
||||
form.keepExtensions = true;
|
||||
|
||||
form.parse(req, function(err, fields, files)
|
||||
{
|
||||
//save the path of the uploaded file
|
||||
srcFile = files.file.path;
|
||||
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
|
||||
//convert file to text
|
||||
function(callback)
|
||||
{
|
||||
var randNum = Math.floor(Math.random()*new Date().getTime());
|
||||
destFile = "/tmp/eplite_import_" + randNum + ".txt";
|
||||
abiword.convertFile(srcFile, destFile, "txt", callback);
|
||||
},
|
||||
|
||||
//get the pad object
|
||||
function(callback)
|
||||
{
|
||||
padManager.getPad(padId, function(err, _pad)
|
||||
{
|
||||
pad = _pad;
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
|
||||
//read the text
|
||||
function(callback)
|
||||
{
|
||||
fs.readFile(destFile, "utf8", function(err, _text)
|
||||
{
|
||||
text = _text;
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
|
||||
//change text of the pad and broadcast the changeset
|
||||
function(callback)
|
||||
{
|
||||
pad.setText(text);
|
||||
padMessageHandler.updatePadClients(pad, callback);
|
||||
},
|
||||
|
||||
//clean up temporary files
|
||||
function(callback)
|
||||
{
|
||||
async.parallel([
|
||||
function(callback)
|
||||
{
|
||||
fs.unlink(srcFile, callback);
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
fs.unlink(destFile, callback);
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
//close the connection
|
||||
res.send("ok");
|
||||
|
||||
if(err) throw err;
|
||||
});
|
||||
}
|
|
@ -191,6 +191,20 @@ Class('Pad', {
|
|||
return this.atext.text;
|
||||
},
|
||||
|
||||
setText : function(newText)
|
||||
{
|
||||
//clean the new text
|
||||
newText = exports.cleanText(newText);
|
||||
|
||||
var oldText = this.text();
|
||||
|
||||
//create the changeset
|
||||
var changeset = Changeset.makeSplice(oldText, 0, oldText.length-1, newText);
|
||||
|
||||
//append the changeset
|
||||
this.appendRevision(changeset);
|
||||
},
|
||||
|
||||
appendChatMessage: function(text, userId, time)
|
||||
{
|
||||
this.chatHead++;
|
||||
|
|
|
@ -433,71 +433,7 @@ function handleUserChanges(client, message)
|
|||
pad.appendRevision(nlChangeset);
|
||||
}
|
||||
|
||||
//ex. updatePadClients
|
||||
|
||||
//go trough all sessions on this pad
|
||||
async.forEach(pad2sessions[pad.id], function(session, callback)
|
||||
{
|
||||
var lastRev = sessioninfos[session].rev;
|
||||
|
||||
//https://github.com/caolan/async#whilst
|
||||
//send them all new changesets
|
||||
async.whilst(
|
||||
function (){ return lastRev < pad.getHeadRevisionNumber()},
|
||||
function(callback)
|
||||
{
|
||||
var author, revChangeset;
|
||||
|
||||
var r = ++lastRev;
|
||||
|
||||
async.parallel([
|
||||
function (callback)
|
||||
{
|
||||
pad.getRevisionAuthor(r, function(err, value)
|
||||
{
|
||||
author = value;
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
function (callback)
|
||||
{
|
||||
pad.getRevisionChangeset(r, function(err, value)
|
||||
{
|
||||
revChangeset = value;
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(author == sessioninfos[session].author)
|
||||
{
|
||||
socketio.sockets.sockets[session].json.send({"type":"COLLABROOM","data":{type:"ACCEPT_COMMIT", newRev:r}});
|
||||
}
|
||||
else
|
||||
{
|
||||
var forWire = Changeset.prepareForWire(revChangeset, pad.pool);
|
||||
var wireMsg = {"type":"COLLABROOM","data":{type:"NEW_CHANGES", newRev:r,
|
||||
changeset: forWire.translated,
|
||||
apool: forWire.pool,
|
||||
author: author}};
|
||||
|
||||
socketio.sockets.sockets[session].json.send(wireMsg);
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
},
|
||||
callback
|
||||
);
|
||||
|
||||
sessioninfos[session].rev = pad.getHeadRevisionNumber();
|
||||
},callback);
|
||||
exports.updatePadClients(pad, callback);
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
|
@ -505,6 +441,73 @@ function handleUserChanges(client, message)
|
|||
});
|
||||
}
|
||||
|
||||
exports.updatePadClients = function(pad, callback)
|
||||
{
|
||||
//go trough all sessions on this pad
|
||||
async.forEach(pad2sessions[pad.id], function(session, callback)
|
||||
{
|
||||
var lastRev = sessioninfos[session].rev;
|
||||
|
||||
//https://github.com/caolan/async#whilst
|
||||
//send them all new changesets
|
||||
async.whilst(
|
||||
function (){ return lastRev < pad.getHeadRevisionNumber()},
|
||||
function(callback)
|
||||
{
|
||||
var author, revChangeset;
|
||||
|
||||
var r = ++lastRev;
|
||||
|
||||
async.parallel([
|
||||
function (callback)
|
||||
{
|
||||
pad.getRevisionAuthor(r, function(err, value)
|
||||
{
|
||||
author = value;
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
function (callback)
|
||||
{
|
||||
pad.getRevisionChangeset(r, function(err, value)
|
||||
{
|
||||
revChangeset = value;
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(author == sessioninfos[session].author)
|
||||
{
|
||||
socketio.sockets.sockets[session].json.send({"type":"COLLABROOM","data":{type:"ACCEPT_COMMIT", newRev:r}});
|
||||
}
|
||||
else
|
||||
{
|
||||
var forWire = Changeset.prepareForWire(revChangeset, pad.pool);
|
||||
var wireMsg = {"type":"COLLABROOM","data":{type:"NEW_CHANGES", newRev:r,
|
||||
changeset: forWire.translated,
|
||||
apool: forWire.pool,
|
||||
author: author}};
|
||||
|
||||
socketio.sockets.sockets[session].json.send(wireMsg);
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
},
|
||||
callback
|
||||
);
|
||||
|
||||
sessioninfos[session].rev = pad.getHeadRevisionNumber();
|
||||
},callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from the Etherpad Source Code. Don't know what this methode does excatly...
|
||||
*/
|
||||
|
|
|
@ -32,6 +32,7 @@ var express = require('express');
|
|||
var path = require('path');
|
||||
var minify = require('./minify');
|
||||
var exportHandler;
|
||||
var importHandler;
|
||||
var exporthtml;
|
||||
var readOnlyManager;
|
||||
|
||||
|
@ -51,7 +52,7 @@ catch(e)
|
|||
|
||||
var serverName = "Etherpad-Lite " + version + " (http://j.mp/ep-lite)";
|
||||
|
||||
//cache a week
|
||||
//cache 6 hours
|
||||
exports.maxAge = 1000*60*60*6;
|
||||
|
||||
async.waterfall([
|
||||
|
@ -70,6 +71,7 @@ async.waterfall([
|
|||
readOnlyManager = require("./ReadOnlyManager");
|
||||
exporthtml = require("./exporters/exporthtml");
|
||||
exportHandler = require('./ExportHandler');
|
||||
importHandler = require('./ImportHandler');
|
||||
|
||||
//set logging
|
||||
if(settings.logHTTP)
|
||||
|
@ -215,6 +217,20 @@ async.waterfall([
|
|||
exportHandler.doExport(req, res, req.params.pad, req.params.type);
|
||||
});
|
||||
|
||||
//handle import requests
|
||||
app.post('/p/:pad/import', function(req, res, next)
|
||||
{
|
||||
//if abiword is disabled, skip handling this request
|
||||
if(settings.abiword == null)
|
||||
{
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
res.header("Server", serverName);
|
||||
importHandler.doImport(req, res, req.params.pad);
|
||||
});
|
||||
|
||||
//serve index.html under /
|
||||
app.get('/', function(req, res)
|
||||
{
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
"keywords" : ["etherpad", "realtime", "collaborative", "editor"],
|
||||
"author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com>",
|
||||
"contributors": [
|
||||
{ "name": "Hans Pinckaers"}
|
||||
{ "name": "John McLear",
|
||||
"name": "Hans Pinckaers"}
|
||||
],
|
||||
"dependencies" : {
|
||||
"socket.io" : "0.7.7",
|
||||
|
@ -15,7 +16,8 @@
|
|||
"express" : "2.4.2",
|
||||
"clean-css" : "0.2.4",
|
||||
"uglify-js" : "1.0.4",
|
||||
"gzip" : "0.1.0"
|
||||
"gzip" : "0.1.0",
|
||||
"formidable" : "1.0.2"
|
||||
},
|
||||
"version" : "0.0.4"
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ var padimpexp = (function()
|
|||
|
||||
function addImportFrames()
|
||||
{
|
||||
$("#impexp-import .importframe").remove();
|
||||
$('#impexp-import').append(
|
||||
$('<iframe style="display: none;" name="importiframe" class="importframe"></iframe>'));
|
||||
$("#import .importframe").remove();
|
||||
var iframe = $('<iframe style="display: none;" name="importiframe" class="importframe"></iframe>');
|
||||
$('#import').append(iframe);
|
||||
}
|
||||
|
||||
function fileInputUpdated()
|
||||
|
@ -64,7 +64,7 @@ var padimpexp = (function()
|
|||
$('#importmessagefail').fadeOut("fast");
|
||||
var ret = window.confirm("Importing a file will overwrite the current text of the pad." + " Are you sure you want to proceed?");
|
||||
if (ret)
|
||||
{
|
||||
{
|
||||
hidePanelCall = paddocbar.hideLaterIfNoOtherInteraction();
|
||||
currentImportTimer = window.setTimeout(function()
|
||||
{
|
||||
|
@ -88,6 +88,11 @@ var padimpexp = (function()
|
|||
}, 0);
|
||||
$('#importarrow').stop(true, true).hide();
|
||||
$('#importstatusball').show();
|
||||
|
||||
$("#import .importframe").load(function()
|
||||
{
|
||||
importDone();
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -225,6 +230,8 @@ var padimpexp = (function()
|
|||
var self = {
|
||||
init: function()
|
||||
{
|
||||
$("#importform").get(0).setAttribute('action', document.location.href + "/import");
|
||||
|
||||
$("#impexp-close").click(function()
|
||||
{
|
||||
paddocbar.setShownPanel(null);
|
||||
|
@ -249,13 +256,13 @@ var padimpexp = (function()
|
|||
disable: function()
|
||||
{
|
||||
$("#impexp-disabled-clickcatcher").show();
|
||||
$("#impexp-import").css('opacity', 0.5);
|
||||
$("#import").css('opacity', 0.5);
|
||||
$("#impexp-export").css('opacity', 0.5);
|
||||
},
|
||||
enable: function()
|
||||
{
|
||||
$("#impexp-disabled-clickcatcher").hide();
|
||||
$("#impexp-import").css('opacity', 1);
|
||||
$("#import").css('opacity', 1);
|
||||
$("#impexp-export").css('opacity', 1);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -208,7 +208,7 @@ We removed this feature cause its not worth the space it needs in the editbar
|
|||
|
||||
<div id="import">
|
||||
Import from text file, HTML, Word, or RTF:<br/><br/>
|
||||
<form id="importform" method="post" action="import" target="imporiframe" enctype="multipart/form-data">
|
||||
<form id="importform" method="post" action="" target="importiframe" enctype="multipart/form-data">
|
||||
<div class="importformdiv" id="importformfilediv">
|
||||
<input type="file" name="file" size="20" id="importfileinput" />
|
||||
<div class="importmessage" id="importmessagefail"></div>
|
||||
|
@ -222,7 +222,7 @@ We removed this feature cause its not worth the space it needs in the editbar
|
|||
<img alt="" id="importarrow" src="/static/img/leftarrow.png" align="top" />
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="importexportline"></div>
|
||||
|
|
Loading…
Reference in New Issue