diff --git a/bin/installDeps.sh b/bin/installDeps.sh index cb3676063..3fd6da747 100755 --- a/bin/installDeps.sh +++ b/bin/installDeps.sh @@ -20,13 +20,6 @@ hash node > /dev/null 2>&1 || { exit 1 } -#check node version -NODE_VERSION=$(node --version) -if [ ! $(echo $NODE_VERSION | cut -d "." -f 1-2) = "v0.4" ]; then - echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.4.x" >&2 - exit 1 -fi - #Is npm installed? hash npm > /dev/null 2>&1 || { echo "Please install npm ( http://npmjs.org )" >&2 diff --git a/node/db/API.js b/node/db/API.js index 9912b098d..2069ce688 100644 --- a/node/db/API.js +++ b/node/db/API.js @@ -25,6 +25,7 @@ var groupManager = require("./GroupManager"); var authorManager = require("./AuthorManager"); var sessionManager = require("./SessionManager"); var async = require("async"); +var exportHtml = require("../utils/ExportHtml"); /**********************/ /**GROUP FUNCTIONS*****/ @@ -169,6 +170,90 @@ exports.setText = function(padID, text, callback) }); } +/** +getHTML(padID, [rev]) returns the html of a pad + +Example returns: + +{code: 0, message:"ok", data: {text:"Welcome Text"}} +{code: 1, message:"padID does not exist", data: null} +*/ +exports.getHTML = function(padID, rev, callback) +{ + if(typeof rev == "function") + { + callback = rev; + rev = undefined; + } + + if (rev !== undefined && typeof rev != "number") + { + if (!isNaN(parseInt(rev))) + { + rev = parseInt(rev); + } + else + { + callback({stop: "rev is not a number"}); + return; + } + } + + if(rev !== undefined && rev < 0) + { + callback({stop: "rev is a negative number"}); + return; + } + + if(rev !== undefined && !is_int(rev)) + { + callback({stop: "rev is a float value"}); + return; + } + + getPadSafe(padID, true, function(err, pad) + { + if(err) + { + callback(err); + return; + } + + //the client asked for a special revision + if(rev !== undefined) + { + //check if this is a valid revision + if(rev > pad.getHeadRevisionNumber()) + { + callback({stop: "rev is higher than the head revision of the pad"}); + return; + } + + //get the html of this revision + exportHtml.getPadHTML(pad, rev, function(err, html) + { + if(!err) + { + data = {html: html}; + } + callback(err, data); + }); + } + //the client wants the latest text, lets return it to him + else + { + exportHtml.getPadHTML(pad, undefined, function (err, html) + { + if(!err) + { + data = {html: html}; + } + callback(err, data); + }); + } + }); +} + /*****************/ /**PAD FUNCTIONS */ /*****************/ diff --git a/node/handler/APIHandler.js b/node/handler/APIHandler.js index 34d63f18d..57eeeb734 100644 --- a/node/handler/APIHandler.js +++ b/node/handler/APIHandler.js @@ -50,6 +50,7 @@ var functions = { "listSessionsOfAuthor" : ["authorID"], "getText" : ["padID", "rev"], "setText" : ["padID", "text"], + "getHTML" : ["padID", "rev"], "getRevisionsCount" : ["padID"], "deletePad" : ["padID"], "getReadOnlyID" : ["padID"], diff --git a/node/handler/ExportHandler.js b/node/handler/ExportHandler.js index a87219bb7..8cc74747d 100644 --- a/node/handler/ExportHandler.js +++ b/node/handler/ExportHandler.js @@ -81,10 +81,9 @@ exports.doExport = function(req, res, padId, type) res.send(html); callback("stop"); } - //write the html export to a file - else + else //write the html export to a file { - randNum = Math.floor(Math.random()*new Date().getTime()); + randNum = Math.floor(Math.random()*0xFFFFFFFF); srcFile = tempDirectory + "/eplite_export_" + randNum + ".html"; fs.writeFile(srcFile, html, callback); } @@ -114,10 +113,13 @@ exports.doExport = function(req, res, padId, type) function(callback) { //100ms delay to accomidate for slow windows fs - setTimeout(function() - { - fs.unlink(destFile, callback); - }, 100); + if(os.type().indexOf("Windows") > -1) + { + setTimeout(function() + { + fs.unlink(destFile, callback); + }, 100); + } } ], callback); } diff --git a/node/handler/ImportHandler.js b/node/handler/ImportHandler.js index 8936e488a..a1ddf9924 100644 --- a/node/handler/ImportHandler.js +++ b/node/handler/ImportHandler.js @@ -61,10 +61,19 @@ exports.doImport = function(req, res, padId) form.parse(req, function(err, fields, files) { - //save the path of the uploaded file - srcFile = files.file.path; - - callback(err); + //the upload failed, stop at this point + if(err || files.file === undefined) + { + console.warn("Uploading Error: " + err.stack); + callback("uploadFailed"); + } + //everything ok, continue + else + { + //save the path of the uploaded file + srcFile = files.file.path; + callback(); + } }); }, @@ -157,6 +166,13 @@ exports.doImport = function(req, res, padId) } ], function(err) { + //the upload failed, there is nothing we can do, send a 500 + if(err == "uploadFailed") + { + res.send(500); + return; + } + if(err) throw err; //close the connection diff --git a/node/handler/PadMessageHandler.js b/node/handler/PadMessageHandler.js index f89f4934c..5dccafc54 100644 --- a/node/handler/PadMessageHandler.js +++ b/node/handler/PadMessageHandler.js @@ -136,7 +136,7 @@ exports.handleDisconnect = function(client) { if(pad2sessions[sessionPad][i] == client.id) { - delete pad2sessions[sessionPad][i]; + pad2sessions[sessionPad].splice(i, 1); break; } } @@ -193,7 +193,7 @@ exports.handleMessage = function(client, message) //if the message type is unkown, throw an exception else { - messageLogger.warn("Droped message, unkown Message Type " + message.type); + messageLogger.warn("Dropped message, unkown Message Type " + message.type + ": " + JSON.stringify(message)); } } @@ -272,12 +272,12 @@ function handleSuggestUserName(client, message) //check if all ok if(message.data.payload.newName == null) { - messageLogger.warn("Droped message, suggestUserName Message has no newName!"); + messageLogger.warn("Dropped message, suggestUserName Message has no newName!"); return; } if(message.data.payload.unnamedId == null) { - messageLogger.warn("Droped message, suggestUserName Message has no unnamedId!"); + messageLogger.warn("Dropped message, suggestUserName Message has no unnamedId!"); return; } @@ -304,7 +304,7 @@ function handleUserInfoUpdate(client, message) //check if all ok if(message.data.userInfo.colorId == null) { - messageLogger.warn("Droped message, USERINFO_UPDATE Message has no colorId!"); + messageLogger.warn("Dropped message, USERINFO_UPDATE Message has no colorId!"); return; } @@ -348,17 +348,17 @@ function handleUserChanges(client, message) //check if all ok if(message.data.baseRev == null) { - messageLogger.warn("Droped message, USER_CHANGES Message has no baseRev!"); + messageLogger.warn("Dropped message, USER_CHANGES Message has no baseRev!"); return; } if(message.data.apool == null) { - messageLogger.warn("Droped message, USER_CHANGES Message has no apool!"); + messageLogger.warn("Dropped message, USER_CHANGES Message has no apool!"); return; } if(message.data.changeset == null) { - messageLogger.warn("Droped message, USER_CHANGES Message has no changeset!"); + messageLogger.warn("Dropped message, USER_CHANGES Message has no changeset!"); return; } @@ -600,22 +600,22 @@ function handleClientReady(client, message) //check if all ok if(!message.token) { - messageLogger.warn("Droped message, CLIENT_READY Message has no token!"); + messageLogger.warn("Dropped message, CLIENT_READY message has no token!"); return; } if(!message.padId) { - messageLogger.warn("Droped message, CLIENT_READY Message has no padId!"); + messageLogger.warn("Dropped message, CLIENT_READY message has no padId!"); return; } if(!message.protocolVersion) { - messageLogger.warn("Droped message, CLIENT_READY Message has no protocolVersion!"); + messageLogger.warn("Dropped message, CLIENT_READY message has no protocolVersion!"); return; } if(message.protocolVersion != 2) { - messageLogger.warn("Droped message, CLIENT_READY Message has a unkown protocolVersion '" + message.protocolVersion + "'!"); + messageLogger.warn("Dropped message, CLIENT_READY message has an unkown protocolVersion '" + message.protocolVersion + "'!"); return; } diff --git a/node/handler/TimesliderMessageHandler.js b/node/handler/TimesliderMessageHandler.js index a06ab54c8..fa272cc91 100644 --- a/node/handler/TimesliderMessageHandler.js +++ b/node/handler/TimesliderMessageHandler.js @@ -77,7 +77,7 @@ exports.handleMessage = function(client, message) //if the message type is unkown, throw an exception else { - messageLogger.warn("Droped message, unkown Message Type: '" + message.type + "'"); + messageLogger.warn("Dropped message, unkown Message Type: '" + message.type + "'"); } } @@ -85,7 +85,7 @@ function handleClientReady(client, message) { if(message.padId == null) { - messageLogger.warn("Droped message, changeset request has no padId!"); + messageLogger.warn("Dropped message, changeset request has no padId!"); return; } @@ -106,27 +106,27 @@ function handleChangesetRequest(client, message) //check if all ok if(message.data == null) { - messageLogger.warn("Droped message, changeset request has no data!"); + messageLogger.warn("Dropped message, changeset request has no data!"); return; } if(message.padId == null) { - messageLogger.warn("Droped message, changeset request has no padId!"); + messageLogger.warn("Dropped message, changeset request has no padId!"); return; } if(message.data.granularity == null) { - messageLogger.warn("Droped message, changeset request has no granularity!"); + messageLogger.warn("Dropped message, changeset request has no granularity!"); return; } if(message.data.start == null) { - messageLogger.warn("Droped message, changeset request has no start!"); + messageLogger.warn("Dropped message, changeset request has no start!"); return; } if(message.data.requestID == null) { - messageLogger.warn("Droped message, changeset request has no requestID!"); + messageLogger.warn("Dropped message, changeset request has no requestID!"); return; } diff --git a/node/utils/ExportHtml.js b/node/utils/ExportHtml.js index dce156ec8..782bb7016 100644 --- a/node/utils/ExportHtml.js +++ b/node/utils/ExportHtml.js @@ -85,6 +85,8 @@ function getPadHTML(pad, revNum, callback) }); } +exports.getPadHTML = getPadHTML; + function getHTMLFromAtext(pad, atext) { var apool = pad.apool(); @@ -119,8 +121,10 @@ function getHTMLFromAtext(pad, atext) var taker = Changeset.stringIterator(text); var assem = Changeset.stringAssembler(); + var openTags = []; function emitOpenTag(i) { + openTags.unshift(i); assem.append('<'); assem.append(tags[i]); assem.append('>'); @@ -128,10 +132,27 @@ function getHTMLFromAtext(pad, atext) function emitCloseTag(i) { + openTags.shift(); assem.append(''); assem.append(tags[i]); assem.append('>'); } + + function orderdCloseTags(tags2close) + { + for(var i=0;i= 0; i--) { if (propVals[i] === LEAVE) { - emitCloseTag(i); + //emitCloseTag(i); + tags2close.push(i); propVals[i] = false; } else if (propVals[i] === STAY) { - emitCloseTag(i); + //emitCloseTag(i); + tags2close.push(i); } } + + orderdCloseTags(tags2close); + for (var i = 0; i < propVals.length; i++) { if (propVals[i] === ENTER || propVals[i] === STAY) @@ -231,18 +259,27 @@ function getHTMLFromAtext(pad, atext) { chars--; // exclude newline at end of line, if present } + var s = taker.take(chars); - + + //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), ""); + assem.append(_escapeHTML(s)); } // end iteration over spans in line + + var tags2close = []; for (var i = propVals.length - 1; i >= 0; i--) { if (propVals[i]) { - emitCloseTag(i); + tags2close.push(i); propVals[i] = false; } } + + orderdCloseTags(tags2close); } // end processNextChars if (urls) { diff --git a/package.json b/package.json index b90f789a7..f1c30caa7 100644 --- a/package.json +++ b/package.json @@ -3,23 +3,23 @@ "description" : "A Etherpad based on node.js", "homepage" : "https://github.com/Pita/etherpad-lite", "keywords" : ["etherpad", "realtime", "collaborative", "editor"], - "author" : "Peter 'Pita' Martischka ", + "author" : "Peter 'Pita' Martischka - Primary Technology Ltd", "contributors": [ { "name": "John McLear", "name": "Hans Pinckaers", "name": "Robin Buse"} ], "dependencies" : { - "socket.io" : "0.7.9", - "ueberDB" : "0.1.2", - "async" : "0.1.9", - "joose" : "3.18.0", - "express" : "2.4.5", + "socket.io" : "0.8.7", + "ueberDB" : "0.1.3", + "async" : "0.1.15", + "joose" : "3.50.0", + "express" : "2.5.0", "clean-css" : "0.2.4", - "uglify-js" : "1.0.7", + "uglify-js" : "1.1.1", "gzip" : "0.1.0", - "formidable" : "1.0.2", - "log4js" : "0.3.8" + "formidable" : "1.0.7", + "log4js" : "0.3.9" }, "version" : "1.0.0" } diff --git a/static/css/pad.css b/static/css/pad.css index 45385a5b7..3d170c3dd 100644 --- a/static/css/pad.css +++ b/static/css/pad.css @@ -93,7 +93,7 @@ a img } input[type="file"] { - color: #fff; + color: #000; } #editbar ul li.separator diff --git a/static/index.html b/static/index.html index a8d1beeca..c353fbb0c 100644 --- a/static/index.html +++ b/static/index.html @@ -86,12 +86,13 @@ input[type="submit"]::-moz-focus-inner { border: 0 } @-moz-document url-prefix() { input[type="submit"] { padding: 7px } } + New Pador create/open a Pad with the name - - + + @@ -123,4 +124,5 @@ //start the costum js if(typeof costumStart == "function") costumStart(); +