From 053e48c3f4e5725b173eb41f86407ca85306b77a Mon Sep 17 00:00:00 2001 From: Peter 'Pita' Martischka Date: Mon, 1 Aug 2011 12:08:18 +0100 Subject: [PATCH 1/4] Secure the call of the costumStart function Author: Peter 'Pita' Martischka --- static/index.html | 2 +- static/js/pad2.js | 2 +- static/timeslider.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/static/index.html b/static/index.html index b7085458b..1cc71bd9b 100644 --- a/static/index.html +++ b/static/index.html @@ -125,6 +125,6 @@ } //start the costum js - if(costumStart) costumStart(); + if(typeof costumStart == "function") costumStart(); diff --git a/static/js/pad2.js b/static/js/pad2.js index aa1f7ccd7..f442607d7 100644 --- a/static/js/pad2.js +++ b/static/js/pad2.js @@ -30,7 +30,7 @@ $(document).ready(function() } //start the costum js - if(costumStart) costumStart(); + if(typeof costumStart == "function") costumStart(); handshake(); }); diff --git a/static/timeslider.html b/static/timeslider.html index fbcbc149e..110b6d128 100644 --- a/static/timeslider.html +++ b/static/timeslider.html @@ -58,7 +58,7 @@ $(document).ready(function () { //start the costum js - if(costumStart) costumStart(); + if(typeof costumStart == "function") costumStart(); //get the padId out of the url var urlParts= document.location.pathname.split("/"); From 9a71cc4729f70e9e77cd3c44e1b4c611f7d30532 Mon Sep 17 00:00:00 2001 From: Peter 'Pita' Martischka Date: Mon, 1 Aug 2011 18:45:28 +0100 Subject: [PATCH 2/4] replaced tabs with spaces --- node/db/Pad.js | 558 ++++++++++++++++++++++++------------------------- 1 file changed, 279 insertions(+), 279 deletions(-) diff --git a/node/db/Pad.js b/node/db/Pad.js index f52c16c7e..d80098701 100644 --- a/node/db/Pad.js +++ b/node/db/Pad.js @@ -19,150 +19,150 @@ exports.cleanText = function (txt) { Class('Pad', { - // these are the properties - has : { - - atext : { - is : 'rw', // readwrite - init : function() { return Changeset.makeAText("\n"); } // first value - }, // atext - - pool : { - is: 'rw', - init : function() { return AttributePoolFactory.createAttributePool(); }, - getterName : 'apool' // legacy - }, // pool - - head : { - is : 'rw', - init : -1, - getterName : 'getHeadRevisionNumber' - }, // head - - chatHead : { - is: 'rw', - init: -1 - }, // chatHead - - id : { is : 'r' } - }, + // these are the properties + has : { + + atext : { + is : 'rw', // readwrite + init : function() { return Changeset.makeAText("\n"); } // first value + }, // atext + + pool : { + is: 'rw', + init : function() { return AttributePoolFactory.createAttributePool(); }, + getterName : 'apool' // legacy + }, // pool + + head : { + is : 'rw', + init : -1, + getterName : 'getHeadRevisionNumber' + }, // head + + chatHead : { + is: 'rw', + init: -1 + }, // chatHead + + id : { is : 'r' } + }, - methods : { - - BUILD : function (id) - { + methods : { + + BUILD : function (id) + { return { 'id' : id, } }, - - appendRevision : function(aChangeset, author) - { - if(!author) - author = ''; + + appendRevision : function(aChangeset, author) + { + if(!author) + author = ''; - var newAText = Changeset.applyToAText(aChangeset, this.atext, this.pool); - Changeset.copyAText(newAText, this.atext); - - var newRev = ++this.head; - - var newRevData = {}; - newRevData.changeset = aChangeset; - newRevData.meta = {}; - newRevData.meta.author = author; - newRevData.meta.timestamp = new Date().getTime(); - - //ex. getNumForAuthor - if(author != '') - this.pool.putAttrib(['author', author || '']); - - if(newRev % 100 == 0) - { - newRevData.meta.atext = this.atext; - } - - db.set("pad:"+this.id+":revs:"+newRev, newRevData); - db.set("pad:"+this.id, {atext: this.atext, pool: this.pool.toJsonable(), head: this.head, chatHead: this.chatHead}); - }, //appendRevision - - getRevisionChangeset : function(revNum, callback) - { - db.getSub("pad:"+this.id+":revs:"+revNum, ["changeset"], callback); - }, // getRevisionChangeset - - getRevisionAuthor : function(revNum, callback) - { - db.getSub("pad:"+this.id+":revs:"+revNum, ["meta", "author"], callback); - }, // getRevisionAuthor - - getRevisionDate : function(revNum, callback) - { - db.getSub("pad:"+this.id+":revs:"+revNum, ["meta", "timestamp"], callback); - }, // getRevisionAuthor - - getAllAuthors : function() - { - var authors = []; + var newAText = Changeset.applyToAText(aChangeset, this.atext, this.pool); + Changeset.copyAText(newAText, this.atext); + + var newRev = ++this.head; + + var newRevData = {}; + newRevData.changeset = aChangeset; + newRevData.meta = {}; + newRevData.meta.author = author; + newRevData.meta.timestamp = new Date().getTime(); + + //ex. getNumForAuthor + if(author != '') + this.pool.putAttrib(['author', author || '']); + + if(newRev % 100 == 0) + { + newRevData.meta.atext = this.atext; + } + + db.set("pad:"+this.id+":revs:"+newRev, newRevData); + db.set("pad:"+this.id, {atext: this.atext, pool: this.pool.toJsonable(), head: this.head, chatHead: this.chatHead}); + }, //appendRevision + + getRevisionChangeset : function(revNum, callback) + { + db.getSub("pad:"+this.id+":revs:"+revNum, ["changeset"], callback); + }, // getRevisionChangeset + + getRevisionAuthor : function(revNum, callback) + { + db.getSub("pad:"+this.id+":revs:"+revNum, ["meta", "author"], callback); + }, // getRevisionAuthor + + getRevisionDate : function(revNum, callback) + { + db.getSub("pad:"+this.id+":revs:"+revNum, ["meta", "timestamp"], callback); + }, // getRevisionAuthor + + getAllAuthors : function() + { + var authors = []; - for(key in this.pool.numToAttrib) - { - if(this.pool.numToAttrib[key][0] == "author" && this.pool.numToAttrib[key][1] != "") - { - authors.push(this.pool.numToAttrib[key][1]); - } - } - - return authors; - }, - - getInternalRevisionAText : function(targetRev, callback) - { - var _this = this; - - var keyRev = this.getKeyRevisionNumber(targetRev); - var atext; - var changesets = []; - - //find out which changesets are needed - var neededChangesets = []; - var curRev = keyRev; - while (curRev < targetRev) - { + for(key in this.pool.numToAttrib) + { + if(this.pool.numToAttrib[key][0] == "author" && this.pool.numToAttrib[key][1] != "") + { + authors.push(this.pool.numToAttrib[key][1]); + } + } + + return authors; + }, + + getInternalRevisionAText : function(targetRev, callback) + { + var _this = this; + + var keyRev = this.getKeyRevisionNumber(targetRev); + var atext; + var changesets = []; + + //find out which changesets are needed + var neededChangesets = []; + var curRev = keyRev; + while (curRev < targetRev) + { curRev++; neededChangesets.push(curRev); } - - async.series([ - //get all needed data out of the database - function(callback) - { - async.parallel([ - //get the atext of the key revision - function (callback) - { - db.getSub("pad:"+_this.id+":revs:"+keyRev, ["meta", "atext"], function(err, _atext) - { - atext = Changeset.cloneAText(_atext); - callback(err); - }); - }, - //get all needed changesets - function (callback) - { - async.forEach(neededChangesets, function(item, callback) - { - _this.getRevisionChangeset(item, function(err, changeset) - { - changesets[item] = changeset; - callback(err); - }); - }, callback); - } - ], callback); - }, - //apply all changesets to the key changeset - function(callback) - { + + async.series([ + //get all needed data out of the database + function(callback) + { + async.parallel([ + //get the atext of the key revision + function (callback) + { + db.getSub("pad:"+_this.id+":revs:"+keyRev, ["meta", "atext"], function(err, _atext) + { + atext = Changeset.cloneAText(_atext); + callback(err); + }); + }, + //get all needed changesets + function (callback) + { + async.forEach(neededChangesets, function(item, callback) + { + _this.getRevisionChangeset(item, function(err, changeset) + { + changesets[item] = changeset; + callback(err); + }); + }, callback); + } + ], callback); + }, + //apply all changesets to the key changeset + function(callback) + { var apool = _this.apool(); var curRev = keyRev; @@ -174,118 +174,118 @@ Class('Pad', { } callback(null); - } - ], function(err) - { - callback(err, atext); - }); - }, - - getKeyRevisionNumber : function(revNum) - { - return Math.floor(revNum / 100) * 100; - }, - - text : function() - { - 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++; - //save the chat entry in the database - db.set("pad:"+this.id+":chat:"+this.chatHead, {"text": text, "userId": userId, "time": time}); - //save the new chat head - db.setSub("pad:"+this.id, ["chatHead"], this.chatHead); - }, - - getChatMessage: function(entryNum, callback) - { - var _this = this; - var entry; - - async.series([ - //get the chat entry - function(callback) - { - db.get("pad:"+_this.id+":chat:"+entryNum, function(err, _entry) - { - entry = _entry; - callback(err); - }); - }, - //add the authorName - function(callback) - { - //this chat message doesn't exist, return null - if(entry == null) - { - callback(); - return; - } - - //get the authorName - authorManager.getAuthorName(entry.userId, function(err, authorName) - { - entry.userName = authorName; - callback(err); - }); - } - ], function(err) - { - callback(err, entry); - }); - }, - - getLastChatMessages: function(count, callback) - { - //return an empty array if there are no chat messages - if(this.chatHead == -1) - { - callback(null, []); - return; - } - + } + ], function(err) + { + callback(err, atext); + }); + }, + + getKeyRevisionNumber : function(revNum) + { + return Math.floor(revNum / 100) * 100; + }, + + text : function() + { + 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++; + //save the chat entry in the database + db.set("pad:"+this.id+":chat:"+this.chatHead, {"text": text, "userId": userId, "time": time}); + //save the new chat head + db.setSub("pad:"+this.id, ["chatHead"], this.chatHead); + }, + + getChatMessage: function(entryNum, callback) + { + var _this = this; + var entry; + + async.series([ + //get the chat entry + function(callback) + { + db.get("pad:"+_this.id+":chat:"+entryNum, function(err, _entry) + { + entry = _entry; + callback(err); + }); + }, + //add the authorName + function(callback) + { + //this chat message doesn't exist, return null + if(entry == null) + { + callback(); + return; + } + + //get the authorName + authorManager.getAuthorName(entry.userId, function(err, authorName) + { + entry.userName = authorName; + callback(err); + }); + } + ], function(err) + { + callback(err, entry); + }); + }, + + getLastChatMessages: function(count, callback) + { + //return an empty array if there are no chat messages + if(this.chatHead == -1) + { + callback(null, []); + return; + } + var _this = this; //works only if we decrement the amount, for some reason count--; - //set the startpoint - var start = this.chatHead-count; - if(start < 0) - start = 0; + //set the startpoint + var start = this.chatHead-count; + if(start < 0) + start = 0; - //set the endpoint - var end = this.chatHead; - - //collect the numbers of chat entries and in which order we need them - var neededEntries = []; - var order = 0; - for(var i=start;i<=end; i++) - { - neededEntries.push({entryNum:i, order: order}); - order++; - } - - //get all entries out of the database - var entries = []; - async.forEach(neededEntries, function(entryObject, callback) + //set the endpoint + var end = this.chatHead; + + //collect the numbers of chat entries and in which order we need them + var neededEntries = []; + var order = 0; + for(var i=start;i<=end; i++) + { + neededEntries.push({entryNum:i, order: order}); + order++; + } + + //get all entries out of the database + var entries = []; + async.forEach(neededEntries, function(entryObject, callback) { _this.getChatMessage(entryObject.entryNum, function(err, entry) { @@ -308,44 +308,44 @@ Class('Pad', { callback(err, cleanedEntries); }); - }, - - init : function (callback) - { - var _this = this; - - //try to load the pad - db.get("pad:"+this.id, function(err, value) - { - if(err) - { - callback(err, null); - return; - } - - //if this pad exists, load it - if(value != null) - { - _this.head = value.head; - _this.atext = value.atext; - _this.pool = _this.pool.fromJsonable(value.pool); - - if(value.chatHead != null) - _this.chatHead = value.chatHead; - else - _this.chatHead = -1; - } - //this pad doesn't exist, so create it - else - { - var firstChangeset = Changeset.makeSplice("\n", 0, 0, exports.cleanText(settings.defaultPadText)); - - _this.appendRevision(firstChangeset, ''); - } - - callback(null); - }); + }, + + init : function (callback) + { + var _this = this; + + //try to load the pad + db.get("pad:"+this.id, function(err, value) + { + if(err) + { + callback(err, null); + return; + } + + //if this pad exists, load it + if(value != null) + { + _this.head = value.head; + _this.atext = value.atext; + _this.pool = _this.pool.fromJsonable(value.pool); + + if(value.chatHead != null) + _this.chatHead = value.chatHead; + else + _this.chatHead = -1; + } + //this pad doesn't exist, so create it + else + { + var firstChangeset = Changeset.makeSplice("\n", 0, 0, exports.cleanText(settings.defaultPadText)); + + _this.appendRevision(firstChangeset, ''); + } + + callback(null); + }); } - - }, // methods + + }, // methods }); From 91347a352862e233787294ccbc834383f04085fc Mon Sep 17 00:00:00 2001 From: Peter 'Pita' Martischka Date: Mon, 1 Aug 2011 19:24:11 +0100 Subject: [PATCH 3/4] Improved the README --- README.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d476c9616..51b316f28 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ Visit to test it live. You can find the same instanc # Installation -1. Download latest node.js version from and build it with this instructions .
-The Node.js version of your Linux repository might be too old/new. Please compile from the source to get sure you have the correct version. We support node.js version 0.4.* +1. Download the latest 0.4.x node.js release from and build it with this instructions .
+The Node.js version of your Linux repository might be too old/new. Please compile from the source to get sure you have the correct version. 2. Install npm `curl http://npmjs.org/install.sh | sh` 3. Ensure you have installed the sqlite develob libraries, gzip and git `apt-get install libsqlite3-dev gzip git-core` 4. Clone the git repository `git clone 'git://github.com/Pita/etherpad-lite.git'` @@ -40,11 +40,11 @@ The Node.js version of your Linux repository might be too old/new. Please compil # Next Steps You can modify the settings in the file settings.json -You can update to the latest version with `git pull origin && npm install` +You can update to the latest version with `git pull origin`. The next start with bin/run.sh will update the dependencies -You can debug with `bin/runDebug.sh` +You can debug with `bin/debugRun.sh` -Look at the Wiki: [How to put Etherpad Lite behind a reverse Proxy](https://github.com/Pita/etherpad-lite/wiki/How-to-put-Etherpad-Lite-behind-a-reverse-Proxy), [How to deploy Etherpad Lite as a service](https://github.com/Pita/etherpad-lite/wiki/How-to-deploy-Etherpad-Lite-as-a-service). Feel free to improve these wiki pages +You can find more information in the [wiki](https://github.com/Pita/etherpad-lite/wiki). Feel free to improve these wiki pages # Develop If you're new to git and github, start here . @@ -58,5 +58,13 @@ You can join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) You also help the project, if you only host a ep-lite instance and share your experience with us. +Look at our [FAQ Page](https://github.com/Pita/etherpad-lite/wiki/FAQ) + +# Modules created for this project + +* [ueberDB](https://github.com/Pita/ueberDB) "transforms every database into a object key value store" - manages all database access +* [doc.md](https://github.com/Pita/doc.md) "A simple JSDoc documenation tool that creates markdown for node.js modules exports" - is used to generate the docs +* [channels](https://github.com/Pita/channels) "Event channels in node.js" - ensures that ueberDB operations are atomic and in series for each key + # License [Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html) From 8ca57ffde44cabb229b43b12f06200e6eff9e708 Mon Sep 17 00:00:00 2001 From: Peter 'Pita' Martischka Date: Mon, 1 Aug 2011 19:29:22 +0100 Subject: [PATCH 4/4] Added READMEs to explain the doc folders --- doc/easysync/README.md | 2 ++ doc/jsdoc/README.md | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 doc/easysync/README.md create mode 100644 doc/jsdoc/README.md diff --git a/doc/easysync/README.md b/doc/easysync/README.md new file mode 100644 index 000000000..551487544 --- /dev/null +++ b/doc/easysync/README.md @@ -0,0 +1,2 @@ +# About this folder +We put all documentations we found about the old Etherpad together in this folder. Most of this is still valid for Etherpad Lite \ No newline at end of file diff --git a/doc/jsdoc/README.md b/doc/jsdoc/README.md new file mode 100644 index 000000000..066f3731d --- /dev/null +++ b/doc/jsdoc/README.md @@ -0,0 +1,2 @@ +# About this folder +This is the documentation generated with doc.md. This documentation might be not up to date, you can generate the latest jsdocs with bin/generateJsDoc.sh \ No newline at end of file