This commit is contained in:
Jason Woofenden 2012-11-07 20:47:24 -08:00
commit be4505d7fc
104 changed files with 1479 additions and 1479 deletions

View file

@ -13,7 +13,7 @@ IRC channels: [#etherpad](irc://freenode/#etherpad) ([webchat](http://webchat.fr
* easy to use for people
* using less resources on server side
* easy to embed for admins
* also runable as etherpad lite only
* also runable as etherpad lite only
* keep it maintainable, we don't wanna end ob as the monster Etherpad was
* extensible, as much functionality should be extendable with plugins so changes don't have to be done in core

View file

@ -3,7 +3,7 @@ outdoc_files = $(addprefix out/,$(doc_sources:.md=.html))
docassets = $(addprefix out/,$(wildcard doc/assets/*))
VERSION = $(shell node -e "console.log( require('./src/package.json').version )")
VERSION = $(shell node -e "console.log( require('./src/package.json').version )")
docs: $(outdoc_files) $(docassets)

View file

@ -1,10 +1,10 @@
# Making collaborative editing the standard on the web
# About
Etherpad lite is a really-real time collaborative editor spawned from the Hell fire of Etherpad.
We're reusing the well tested Etherpad easysync library to make it really realtime. Etherpad Lite
is based on node.js ergo is much lighter and more stable than the original Etherpad. Our hope
is that this will encourage more users to use and install a realtime collaborative editor. A smaller, manageable and well
Etherpad lite is a really-real time collaborative editor spawned from the Hell fire of Etherpad.
We're reusing the well tested Etherpad easysync library to make it really realtime. Etherpad Lite
is based on node.js ergo is much lighter and more stable than the original Etherpad. Our hope
is that this will encourage more users to use and install a realtime collaborative editor. A smaller, manageable and well
documented codebase makes it easier for developers to improve the code and contribute towards the project.
**Etherpad vs Etherpad lite**
@ -24,10 +24,10 @@ documented codebase makes it easier for developers to improve the code and contr
<tr>
<td align="right">RAM Usage immediately after start</td><td>257 MB (grows to ~1GB)</td><td>16 MB (grows to ~30MB)</td>
</tr>
</table>
</table>
Etherpad Lite is designed to be easily embeddable and provides a [HTTP API](https://github.com/Pita/etherpad-lite/wiki/HTTP-API)
Etherpad Lite is designed to be easily embeddable and provides a [HTTP API](https://github.com/Pita/etherpad-lite/wiki/HTTP-API)
that allows your web application to manage pads, users and groups. It is recommended to use the client implementations available for this API, listed on [this wiki page](https://github.com/Pita/etherpad-lite/wiki/HTTP-API-client-libraries).
There is also a [jQuery plugin](https://github.com/johnyma22/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website
@ -62,8 +62,8 @@ Update to the latest version with `git pull origin`, then run `bin\installOnWind
[Next steps](#next-steps).
## Linux
You'll need gzip, git, curl, libssl develop libraries, python and gcc.
*For Debian/Ubuntu*: `apt-get install gzip git-core curl python libssl-dev pkg-config build-essential`
You'll need gzip, git, curl, libssl develop libraries, python and gcc.
*For Debian/Ubuntu*: `apt-get install gzip git-core curl python libssl-dev pkg-config build-essential`
*For Fedora/CentOS*: `yum install gzip git-core curl python openssl-devel && yum groupinstall "Development Tools"`
Additionally, you'll need [node.js](http://nodejs.org).
@ -73,7 +73,7 @@ Additionally, you'll need [node.js](http://nodejs.org).
1. Move to a folder where you want to install Etherpad Lite. Clone the git repository `git clone git://github.com/Pita/etherpad-lite.git`
2. Change into the new directory containing the cloned source code `cd etherpad-lite`
Now, run `bin\run.sh` and open <http://127.0.0.1:9001> in your browser.
Now, run `bin\run.sh` and open <http://127.0.0.1:9001> in your browser.
Update to the latest version with `git pull origin`. The next start with bin/run.sh will update the dependencies.

View file

@ -11,26 +11,26 @@ if [ -d "../bin" ]; then
fi
#Is wget installed?
hash wget > /dev/null 2>&1 || {
hash wget > /dev/null 2>&1 || {
echo "Please install wget" >&2
exit 1
exit 1
}
#Is zip installed?
hash zip > /dev/null 2>&1 || {
hash zip > /dev/null 2>&1 || {
echo "Please install zip" >&2
exit 1
exit 1
}
#Is zip installed?
hash unzip > /dev/null 2>&1 || {
hash unzip > /dev/null 2>&1 || {
echo "Please install unzip" >&2
exit 1
exit 1
}
START_FOLDER=$(pwd);
echo "create a clean environment in /tmp/etherpad-lite-win..."
echo "create a clean environment in /tmp/etherpad-lite-win..."
rm -rf /tmp/etherpad-lite-win
cp -ar . /tmp/etherpad-lite-win
cd /tmp/etherpad-lite-win

View file

@ -25,11 +25,11 @@ async.series([
{
db.init(callback);
},
//get the pad
//get the pad
function (callback)
{
padManager = require('../src/node/db/PadManager');
padManager.doesPadExists(padId, function(err, exists)
{
if(!exists)
@ -37,8 +37,8 @@ async.series([
console.error("Pad does not exist");
process.exit(1);
}
padManager.getPad(padId, function(err, _pad)
padManager.getPad(padId, function(err, _pad)
{
pad = _pad;
callback(err);
@ -46,7 +46,7 @@ async.series([
});
},
function (callback)
{
{
//create an array with key kevisions
//key revisions always save the full pad atext
var head = pad.getHeadRevisionNumber();
@ -55,7 +55,7 @@ async.series([
{
keyRevisions.push(i);
}
//run trough all key revisions
async.forEachSeries(keyRevisions, function(keyRev, callback)
{
@ -65,10 +65,10 @@ async.series([
{
revisionsNeeded.push(i);
}
//this array will hold all revision changesets
var revisions = [];
//run trough all needed revisions and get them from the database
async.forEach(revisionsNeeded, function(revNum, callback)
{
@ -84,14 +84,14 @@ async.series([
callback(err);
return;
}
//check if the pad has a pool
if(pad.pool === undefined )
{
console.error("Attribute pool is missing");
process.exit(1);
}
//check if there is a atext in the keyRevisions
if(revisions[keyRev] === undefined || revisions[keyRev].meta === undefined || revisions[keyRev].meta.atext === undefined)
{
@ -99,10 +99,10 @@ async.series([
callback();
return;
}
var apool = pad.pool;
var atext = revisions[keyRev].meta.atext;
for(var i=keyRev+1;i<=keyRev+100 && i<=head; i++)
{
try
@ -118,7 +118,7 @@ async.series([
return;
}
}
callback();
});
}, callback);
@ -126,8 +126,8 @@ async.series([
], function (err)
{
if(err) throw err;
else
{
else
{
console.log("finished");
process.exit(0);
}

View file

@ -27,21 +27,21 @@ log("open output file...");
var sqlOutput = fs.openSync(sqlOutputFile, "w");
var sql = "SET CHARACTER SET UTF8;\n" +
"CREATE TABLE IF NOT EXISTS `store` ( \n" +
"`key` VARCHAR( 100 ) NOT NULL , \n" +
"`value` LONGTEXT NOT NULL , \n" +
"`key` VARCHAR( 100 ) NOT NULL , \n" +
"`value` LONGTEXT NOT NULL , \n" +
"PRIMARY KEY ( `key` ) \n" +
") ENGINE = INNODB;\n" +
") ENGINE = INNODB;\n" +
"START TRANSACTION;\n\n";
fs.writeSync(sqlOutput, sql);
log("done");
//set setings for ep db
var etherpadDB= new mysql.Client();
etherpadDB.host = settings.etherpadDB.host;
etherpadDB.host = settings.etherpadDB.host;
etherpadDB.port = settings.etherpadDB.port;
etherpadDB.database = settings.etherpadDB.database;
etherpadDB.user = settings.etherpadDB.user;
etherpadDB.password = settings.etherpadDB.password;
etherpadDB.database = settings.etherpadDB.database;
etherpadDB.user = settings.etherpadDB.user;
etherpadDB.password = settings.etherpadDB.password;
//get the timestamp once
var timestamp = new Date().getTime();
@ -53,7 +53,7 @@ async.series([
function(callback)
{
log("get all padIds out of the database...");
etherpadDB.query("SELECT ID FROM PAD_META", [], function(err, _padIDs)
{
padIDs = _padIDs;
@ -63,9 +63,9 @@ async.series([
function(callback)
{
log("done");
//create a queue with a concurrency 100
var queue = async.queue(function (padId, callback)
var queue = async.queue(function (padId, callback)
{
convertPad(padId, function(err)
{
@ -73,10 +73,10 @@ async.series([
callback(err);
});
}, 100);
//set the step callback as the queue callback
queue.drain = callback;
//add the padids to the worker queue
for(var i=0,length=padIDs.length;i<length;i++)
{
@ -86,25 +86,25 @@ async.series([
], function(err)
{
if(err) throw err;
//write the groups
var sql = "";
for(var proID in proID2groupID)
{
var groupID = proID2groupID[proID];
var subdomain = proID2subdomain[proID];
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape("group:" + groupID) + ", " + etherpadDB.escape(JSON.stringify(groups[groupID]))+ ");\n";
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape("mapper2group:subdomain:" + subdomain) + ", " + etherpadDB.escape(groupID)+ ");\n";
}
//close transaction
sql+="COMMIT;";
//end the sql file
fs.writeSync(sqlOutput, sql, undefined, "utf-8");
fs.closeSync(sqlOutput);
log("finished.");
process.exit(0);
});
@ -119,7 +119,7 @@ var padsDone = 0;
function incrementPadStats()
{
padsDone++;
if(padsDone%100 == 0)
{
var averageTime = Math.round(padsDone/((new Date().getTime() - startTime)/1000));
@ -150,10 +150,10 @@ function convertPad(padId, callback)
function(callback)
{
var sql = "SELECT * FROM `PAD_CHAT_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_CHAT_META` WHERE ID=?)";
etherpadDB.query(sql, [padId], function(err, results)
{
if(!err)
if(!err)
{
try
{
@ -164,7 +164,7 @@ function convertPad(padId, callback)
}
}catch(e) {err = e}
}
callback(err);
});
},
@ -172,10 +172,10 @@ function convertPad(padId, callback)
function(callback)
{
var sql = "SELECT * FROM `PAD_REVS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVS_META` WHERE ID=?)";
etherpadDB.query(sql, [padId], function(err, results)
{
if(!err)
if(!err)
{
try
{
@ -186,7 +186,7 @@ function convertPad(padId, callback)
}
}catch(e) {err = e}
}
callback(err);
});
},
@ -194,10 +194,10 @@ function convertPad(padId, callback)
function(callback)
{
var sql = "SELECT * FROM `PAD_REVMETA_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVMETA_META` WHERE ID=?)";
etherpadDB.query(sql, [padId], function(err, results)
{
if(!err)
if(!err)
{
try
{
@ -208,7 +208,7 @@ function convertPad(padId, callback)
}
}catch(e) {err = e}
}
callback(err);
});
},
@ -216,7 +216,7 @@ function convertPad(padId, callback)
function(callback)
{
var sql = "SELECT `JSON` FROM `PAD_APOOL` WHERE `ID` = ?";
etherpadDB.query(sql, [padId], function(err, results)
{
if(!err)
@ -226,7 +226,7 @@ function convertPad(padId, callback)
apool=JSON.parse(results[0].JSON).x;
}catch(e) {err = e}
}
callback(err);
});
},
@ -234,10 +234,10 @@ function convertPad(padId, callback)
function(callback)
{
var sql = "SELECT * FROM `PAD_AUTHORS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_AUTHORS_META` WHERE ID=?)";
etherpadDB.query(sql, [padId], function(err, results)
{
if(!err)
if(!err)
{
try
{
@ -248,7 +248,7 @@ function convertPad(padId, callback)
}
}catch(e) {err = e}
}
callback(err);
});
},
@ -256,17 +256,17 @@ function convertPad(padId, callback)
function(callback)
{
var sql = "SELECT JSON FROM `PAD_META` WHERE ID=?";
etherpadDB.query(sql, [padId], function(err, results)
{
if(!err)
if(!err)
{
try
{
padmeta = JSON.parse(results[0].JSON).x;
}catch(e) {err = e}
}
callback(err);
});
},
@ -279,19 +279,19 @@ function convertPad(padId, callback)
callback();
return;
}
//get the proID out of this padID
var proID = padId.split("$")[0];
var sql = "SELECT subDomain FROM pro_domains WHERE ID = ?";
etherpadDB.query(sql, [proID], function(err, results)
{
if(!err)
{
subdomain = results[0].subDomain;
}
callback(err);
});
}
@ -301,105 +301,105 @@ function convertPad(padId, callback)
{
//saves all values that should be written to the database
var values = {};
//this is a pro pad, let's convert it to a group pad
if(padId.indexOf("$") != -1)
{
var padIdParts = padId.split("$");
var proID = padIdParts[0];
var padName = padIdParts[1];
var groupID
//this proID is not converted so far, do it
if(proID2groupID[proID] == null)
{
groupID = "g." + randomString(16);
//create the mappers for this new group
proID2groupID[proID] = groupID;
proID2subdomain[proID] = subdomain;
groups[groupID] = {pads: {}};
}
//use the generated groupID;
groupID = proID2groupID[proID];
//rename the pad
padId = groupID + "$" + padName;
//set the value for this pad in the group
groups[groupID].pads[padId] = 1;
}
try
{
var newAuthorIDs = {};
var oldName2newName = {};
//replace the authors with generated authors
// we need to do that cause etherpad saves pad local authors, etherpad lite uses them global
for(var i in apool.numToAttrib)
{
var key = apool.numToAttrib[i][0];
var value = apool.numToAttrib[i][1];
//skip non authors and anonymous authors
if(key != "author" || value == "")
continue;
//generate new author values
var authorID = "a." + randomString(16);
var authorColorID = authors[i].colorId || Math.floor(Math.random()*32);
var authorName = authors[i].name || null;
//overwrite the authorID of the attribute pool
apool.numToAttrib[i][1] = authorID;
//write the author to the database
values["globalAuthor:" + authorID] = {"colorId" : authorColorID, "name": authorName, "timestamp": timestamp};
//save in mappers
newAuthorIDs[i] = authorID;
oldName2newName[value] = authorID;
}
//save all revisions
for(var i=0;i<changesets.length;i++)
{
values["pad:" + padId + ":revs:" + i] = {changeset: changesets[i],
values["pad:" + padId + ":revs:" + i] = {changeset: changesets[i],
meta : {
author: newAuthorIDs[changesetsMeta[i].a],
timestamp: changesetsMeta[i].t,
atext: changesetsMeta[i].atext || undefined
}};
}
//save all chat messages
for(var i=0;i<chatMessages.length;i++)
{
values["pad:" + padId + ":chat:" + i] = {"text": chatMessages[i].lineText,
"userId": oldName2newName[chatMessages[i].userId],
values["pad:" + padId + ":chat:" + i] = {"text": chatMessages[i].lineText,
"userId": oldName2newName[chatMessages[i].userId],
"time": chatMessages[i].time}
}
//generate the latest atext
var fullAPool = (new AttributePool()).fromJsonable(apool);
var keyRev = Math.floor(padmeta.head / padmeta.keyRevInterval) * padmeta.keyRevInterval;
var atext = changesetsMeta[keyRev].atext;
var curRev = keyRev;
while (curRev < padmeta.head)
while (curRev < padmeta.head)
{
curRev++;
var changeset = changesets[curRev];
atext = Changeset.applyToAText(changeset, atext, fullAPool);
}
values["pad:" + padId] = {atext: atext,
pool: apool,
head: padmeta.head,
values["pad:" + padId] = {atext: atext,
pool: apool,
head: padmeta.head,
chatHead: padmeta.numChatMessages }
}
catch(e)
{
@ -408,13 +408,13 @@ function convertPad(padId, callback)
callback();
return;
}
var sql = "";
for(var key in values)
{
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape(key) + ", " + etherpadDB.escape(JSON.stringify(values[key]))+ ");\n";
}
fs.writeSync(sqlOutput, sql, undefined, "utf-8");
callback();
}
@ -430,24 +430,24 @@ function parsePage(array, pageStart, offsets, data, json)
{
var start = 0;
var lengths = offsets.split(",");
for(var i=0;i<lengths.length;i++)
{
var unitLength = lengths[i];
//skip empty units
if(unitLength == "")
continue;
//parse the number
unitLength = Number(unitLength);
//cut the unit out of data
var unit = data.substr(start, unitLength);
//put it into the array
array[pageStart + i] = json ? JSON.parse(unit) : unit;
//update start
start+=unitLength;
}

View file

@ -1,5 +1,5 @@
{
"etherpadDB":
"etherpadDB":
{
"host": "localhost",
"port": 3306,

View file

@ -11,11 +11,11 @@ fi
#prepare the enviroment
bin/installDeps.sh || exit 1
hash node-inspector > /dev/null 2>&1 || {
hash node-inspector > /dev/null 2>&1 || {
echo "You need to install node-inspector to run the tests!" >&2
echo "You can install it with npm" >&2
echo "Run: npm install -g node-inspector" >&2
exit 1
exit 1
}
node-inspector &
@ -24,5 +24,5 @@ echo "If you are new to node-inspector, take a look at this video: http://youtu.
node --debug node_modules/ep_etherpad-lite/node/server.js $*
#kill node-inspector before ending
#kill node-inspector before ending
kill $!

View file

@ -16,7 +16,7 @@ log4js.setGlobalLogLevel("INFO");
var async = require("async");
var db = require('../node/db/DB');
var dirty = require("dirty")(padId + ".db");
var padManager;
var padManager;
var pad;
var neededDBValues = ["pad:"+padId];
@ -26,12 +26,12 @@ async.series([
{
db.init(callback);
},
//get the pad
//get the pad
function (callback)
{
padManager = require('../node/db/PadManager');
padManager.getPad(padId, function(err, _pad)
padManager.getPad(padId, function(err, _pad)
{
pad = _pad;
callback(err);
@ -45,21 +45,21 @@ async.series([
{
neededDBValues.push("globalAuthor:" + authors[i]);
}
//add all revisions
var revHead = pad.head;
for(var i=0;i<=revHead;i++)
{
neededDBValues.push("pad:"+padId+":revs:" + i);
}
//get all chat values
var chatHead = pad.chatHead;
for(var i=0;i<=chatHead;i++)
{
neededDBValues.push("pad:"+padId+":chat:" + i);
}
//get and set all values
async.forEach(neededDBValues, function(dbkey, callback)
{
@ -67,7 +67,7 @@ async.series([
{
if(err) { callback(err); return}
dbvalue=JSON.parse(dbvalue);
dirty.set(dbkey, dbvalue, callback);
});
}, callback);
@ -75,8 +75,8 @@ async.series([
], function (err)
{
if(err) throw err;
else
{
else
{
console.log("finished");
process.exit();
}

View file

@ -10,35 +10,35 @@ fi
#Is gnu-grep (ggrep) installed on SunOS (Solaris)
if [ $(uname) = "SunOS" ]; then
hash ggrep > /dev/null 2>&1 || {
hash ggrep > /dev/null 2>&1 || {
echo "Please install ggrep (pkg install gnu-grep)" >&2
exit 1
exit 1
}
fi
#Is wget installed?
hash curl > /dev/null 2>&1 || {
hash curl > /dev/null 2>&1 || {
echo "Please install curl" >&2
exit 1
exit 1
}
#Is node installed?
hash node > /dev/null 2>&1 || {
hash node > /dev/null 2>&1 || {
echo "Please install node.js ( http://nodejs.org )" >&2
exit 1
exit 1
}
#Is npm installed?
hash npm > /dev/null 2>&1 || {
hash npm > /dev/null 2>&1 || {
echo "Please install npm ( http://npmjs.org )" >&2
exit 1
exit 1
}
#check npm version
NPM_VERSION=$(npm --version)
if [ ! $(echo $NPM_VERSION | cut -d "." -f 1) = "1" ]; then
echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.x" >&2
exit 1
exit 1
fi
#check node version
@ -46,7 +46,7 @@ NODE_VERSION=$(node --version)
NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2)
if [ ! $NODE_V_MINOR = "v0.8" ] && [ ! $NODE_V_MINOR = "v0.6" ]; then
echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.6.x or v0.8.x" >&2
exit 1
exit 1
fi
#Get the name of the settings file
@ -70,9 +70,9 @@ echo "Ensure that all dependencies are up to date..."
[ -e ep_etherpad-lite ] || ln -s ../src ep_etherpad-lite
cd ep_etherpad-lite
npm install
) || {
) || {
rm -rf node_modules
exit 1
exit 1
}
echo "Ensure jQuery is downloaded and up to date..."
@ -105,7 +105,7 @@ do
if [ ! -f "src/static/custom/$f.js" ]; then
cp "src/static/custom/js.template" "src/static/custom/$f.js" || exit 1
fi
if [ ! -f "src/static/custom/$f.css" ]; then
cp "src/static/custom/css.template" "src/static/custom/$f.css" || exit 1
fi

View file

@ -1,4 +1,4 @@
This load tester is extremely useful for testing how many dormant clients can connect to etherpad lite.
This load tester is extremely useful for testing how many dormant clients can connect to etherpad lite.
TODO:
Emulate characters being typed into a pad
@ -14,7 +14,7 @@ Installed Xvfb and PhantomJS
I installed Xvfb following (roughly) this guide: http://blog.martin-lyness.com/archives/installing-xvfb-on-ubuntu-9-10-karmic-koala
#sudo apt-get install xvfb
#sudo apt-get install xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic
#sudo apt-get install xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic
Launched two instances of Xvfb directly from the terminal:
@ -58,15 +58,15 @@ And finally a launcher script that uses screen to run 400 instances of PhantomJS
### BEGIN SHELL SCRIPT ###
#!/bin/bash
#!/bin/bash
# connect 200 instances to display :0
# connect 200 instances to display :0
for i in {1..200}
do
DISPLAY=:0 screen -d -m phantomjs loader.js http://ec2-50-17-168-xx.compute-1.amazonaws.com:9001/p/pad2 && sleep 2
done
# connect 200 instances to display :1
# connect 200 instances to display :1
for i in {1..200}
do
DISPLAY=:1 screen -d -m phantomjs loader.js http://ec2-50-17-168-xx.compute-1.amazonaws.com:9001/p/pad2 && sleep 2

View file

@ -8,8 +8,8 @@
ERROR_HANDLING=0
# Your email address which should recieve the error messages
EMAIL_ADDRESS="no-reply@example.com"
# Sets the minimun amount of time betweens the sending of error emails.
# This ensures you not get spamed while a endless reboot loop
# Sets the minimun amount of time betweens the sending of error emails.
# This ensures you not get spamed while a endless reboot loop
# It's the time in seconds
TIME_BETWEEN_EMAILS=600 # 10 minutes
@ -37,7 +37,7 @@ do
if [ ! -f $1 ]; then
touch $1 || ( echo "Logfile '$1' is not writeable" && exit 1 )
fi
#check if the file is writeable
if [ ! -w $1 ]; then
echo "Logfile '$1' is not writeable"
@ -46,21 +46,21 @@ do
#start the application
bin/run.sh >>$1 2>>$1
#Send email
if [ $ERROR_HANDLING = 1 ]; then
TIME_NOW=$(date +%s)
TIME_SINCE_LAST_SEND=$(($TIME_NOW - $LAST_EMAIL_SEND))
if [ $TIME_SINCE_LAST_SEND -gt $TIME_BETWEEN_EMAILS ]; then
printf "Server was restared at: $(date)\nThe last 50 lines of the log before the error happens:\n $(tail -n 50 $1)" | mail -s "Pad Server was restarted" $EMAIL_ADDRESS
LAST_EMAIL_SEND=$TIME_NOW
fi
fi
echo "RESTART!" >>$1
#Sleep 10 seconds before restart
sleep 10
done

View file

@ -70,11 +70,11 @@ This creates an empty apool. A apool saves which attributes were used during the
```
> apool.fromJsonable({"numToAttrib":{"0":["author","a.kVnWeomPADAT2pn9"],"1":["bold","true"],"2":["italic","true"]},"nextNum":3});
> console.log(apool)
{ numToAttrib:
{ numToAttrib:
{ '0': [ 'author', 'a.kVnWeomPADAT2pn9' ],
'1': [ 'bold', 'true' ],
'2': [ 'italic', 'true' ] },
attribToNum:
attribToNum:
{ 'author,a.kVnWeomPADAT2pn9': 0,
'bold,true': 1,
'italic,true': 2 },

View file

@ -175,7 +175,7 @@ This hook gets called every time the client receives a message of type `name`. T
`collab_client.js` has a pretty extensive list of message types, if you want to take a look.
##aceStartLineAndCharForPoint-aceEndLineAndCharForPoint
##aceStartLineAndCharForPoint-aceEndLineAndCharForPoint
Called from: src/static/js/ace2_inner.js
Things in context:
@ -190,7 +190,7 @@ Things in context:
This hook is provided to allow a plugin to turn DOM node selection into [line,char] selection.
The return value should be an array of [line,char]
##aceKeyEvent
##aceKeyEvent
Called from: src/static/js/ace2_inner.js
Things in context:
@ -204,7 +204,7 @@ Things in context:
This hook is provided to allow a plugin to handle key events.
The return value should be true if you have handled the event.
##collectContentLineText
##collectContentLineText
Called from: src/static/js/contentcollector.js
Things in context:
@ -217,7 +217,7 @@ Things in context:
This hook allows you to validate/manipulate the text before it's sent to the server side.
The return value should be the validated/manipulated text.
##collectContentLineBreak
##collectContentLineBreak
Called from: src/static/js/contentcollector.js
Things in context:
@ -229,7 +229,7 @@ Things in context:
This hook is provided to allow whether the br tag should induce a new magic domline or not.
The return value should be either true(break the line) or false.
##disableAuthorColorsForThisLine
##disableAuthorColorsForThisLine
Called from: src/static/js/linestylefilter.js
Things in context:

View file

@ -3,7 +3,7 @@
## What can I do with this API?
The API gives another web application control of the pads. The basic functions are
* create/delete pads
* create/delete pads
* grant/forbid access to pads
* get/set pad content
@ -15,30 +15,30 @@ Take a look at [HTTP API client libraries](https://github.com/Pita/etherpad-lite
### Example 1
A portal (such as WordPress) wants to give a user access to a new pad. Let's assume the user have the internal id 7 and his name is michael.
A portal (such as WordPress) wants to give a user access to a new pad. Let's assume the user have the internal id 7 and his name is michael.
Portal maps the internal userid to an etherpad author.
Portal maps the internal userid to an etherpad author.
> Request: `http://pad.domain/api/1/createAuthorIfNotExistsFor?apikey=secret&name=Michael&authorMapper=7`
>
>
> Response: `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}`
Portal maps the internal userid to an etherpad group:
> Request: `http://pad.domain/api/1/createGroupIfNotExistsFor?apikey=secret&groupMapper=7`
>
>
> Response: `{code: 0, message:"ok", data: {groupID: "g.s8oes9dhwrvt0zif"}}`
Portal creates a pad in the userGroup
> Request: `http://pad.domain/api/1/createGroupPad?apikey=secret&groupID=g.s8oes9dhwrvt0zif&padName=samplePad&text=This is the first sentence in the pad`
>
>
> Response: `{code: 0, message:"ok", data: null}`
Portal starts the session for the user on the group:
> Request: `http://pad.domain/api/1/createSession?apikey=secret&groupID=g.s8oes9dhwrvt0zif&authorID=a.s8oes9dhwrvt0zif&validUntil=1312201246`
>
>
> Response: `{"data":{"sessionID": "s.s8oes9dhwrvt0zif"}}`
Portal places the cookie "sessionID" with the given value on the client and creates an iframe including the pad.
@ -50,7 +50,7 @@ A portal (such as WordPress) wants to transform the contents of a pad that multi
Portal retrieves the contents of the pad for entry into the db as a blog post:
> Request: `http://pad.domain/api/1/getText?apikey=secret&padID=g.s8oes9dhwrvt0zif$123`
>
>
> Response: `{code: 0, message:"ok", data: {text:"Welcome Text"}}`
Portal submits content into new blog post
@ -98,7 +98,7 @@ Responses are valid JSON in the following format:
### Authentication
Authentication works via a token that is sent with each request as a post parameter. There is a single token per Etherpad-Lite deployment. This token will be random string, generated by Etherpad-Lite at the first start. It will be saved in APIKEY.txt in the root folder of Etherpad Lite. Only Etherpad Lite and the requesting application knows this key. Token management will not be exposed through this API.
Authentication works via a token that is sent with each request as a post parameter. There is a single token per Etherpad-Lite deployment. This token will be random string, generated by Etherpad-Lite at the first start. It will be saved in APIKEY.txt in the root folder of Etherpad Lite. Only Etherpad Lite and the requesting application knows this key. Token management will not be exposed through this API.
### Node Interoperability
@ -118,7 +118,7 @@ Pads can belong to a group. The padID of grouppads is starting with a groupID li
#### createGroup()
* API >= 1
creates a new group
*Example returns:*
@ -127,7 +127,7 @@ creates a new group
#### createGroupIfNotExistsFor(groupMapper)
* API >= 1
this functions helps you to map your application group ids to etherpad lite group ids
this functions helps you to map your application group ids to etherpad lite group ids
*Example returns:*
* `{code: 0, message:"ok", data: {groupID: g.s8oes9dhwrvt0zif}}`
@ -170,7 +170,7 @@ lists all existing groups
* `{code: 0, message:"ok", data: {groupIDs: []}}`
### Author
These authors are bound to the attributes the users choose (color and name).
These authors are bound to the attributes the users choose (color and name).
#### createAuthor([name])
* API >= 1
@ -183,7 +183,7 @@ creates a new author
#### createAuthorIfNotExistsFor(authorMapper [, name])
* API >= 1
this functions helps you to map your application author ids to etherpad lite author ids
this functions helps you to map your application author ids to etherpad lite author ids
*Example returns:*
* `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}`
@ -290,7 +290,7 @@ returns the text of a pad formatted as HTML
* `{code: 1, message:"padID does not exist", data: null}`
### Pad
Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and its forbidden for normal pads to include a $ in the name.
Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and its forbidden for normal pads to include a $ in the name.
#### createPad(padID [, text])
* API >= 1
@ -398,7 +398,7 @@ returns the timestamp of the last revision of the pad
*Example returns:*
* `{code: 0, message:"ok", data: {lastEdited: 1340815946602}}`
* `{code: 1, message:"padID does not exist", data: null}`
#### sendClientsMessage(padID, msg)
* API >= 1.1

View file

@ -43,9 +43,9 @@ Information about an author
* **colorID** - the colorID of this author as shown in the pad
### mapper2group:$MAPPER
Maps an external application identifier to an internal group
Maps an external application identifier to an internal group
### mapper2author:$MAPPER
Maps an external application identifier to an internal author
Maps an external application identifier to an internal author
### group:$GROUPID
a group of pads

View file

@ -1,4 +1,4 @@
\documentclass{article}
\documentclass{article}
\usepackage{hyperref}
\begin{document}
@ -258,7 +258,7 @@ in Section \ref{follows}.
\paragraph{Proof that $\mathbf{AXY=V \Rightarrow A'X'Y'=VD}$.}
Substituting $A'X'Y'=(AB)(f(B,X))(f(f(X,B),Y))$, we
recall that merges are commutative. So for any two
changesets $P$ and $Q$,
changesets $P$ and $Q$,
$$m(P,Q)=m(Q,P)=Qf(Q,P)=Pf(P,Q)$$
Applying this to the relation above, we see
@ -267,7 +267,7 @@ A'X'Y'&=& AB f(B,X) f(f(X,B),Y) \\
&=&AX f(X,B) f(f(X,B),Y) \\
&=&A X Y f(Y, f(X,B)) \\
&=&A X Y D \\
&=&V D
&=&V D
\end{eqnarray*}
As claimed.
@ -348,7 +348,7 @@ the client's changeset $C$, it does five things:
server's most recent revision number, which we call
$r_H$ ($H$ for HEAD). $C'$ can be computed using
follows (Section \ref{follows}). Remember that the server has a series of
changesets,
changesets,
$$S_0\rightarrow S_1\rightarrow \ldots S_{r_c}\rightarrow S_{r_c+1} \rightarrow \ldots \rightarrow S_{r_H} $$
$C$ is relative to $S_{r_c}$, but we need to compute $C'$ relative to $S_{r_H}$.
We can compute a new $C$ relative to $S_{r_c+1}$ by computing $f(S_{r_c+1},C)$. Similarly we can repeat for

View file

@ -1,7 +1,7 @@
\documentclass[12pt]{article}
\usepackage[T1]{fontenc}
\usepackage[USenglish]{babel}
\usepackage[USenglish]{babel}
\begin{document}
@ -68,7 +68,7 @@ Here are descriptions of the operations, where capital
letters are variables:
\begin{description}
\item{{\bf :N}} \quad \\
\item{{\bf :N}} \quad \\
Source text has length $N$ (must be first op)
\item{{\bf >N}} \quad \\
Final text is $N$ (positive) characters longer than source

View file

@ -72,7 +72,7 @@ Here are descriptions of the operations, where capital letters are variables:
"-N" : Skip over (delete) N characters from the source text, none of them newlines
"=N" : Keep N characters from the source text, none of them newlines
"|L+N" : Insert N characters from the source text, containing L newlines. The last
character inserted MUST be a newline, but not the (new) document's final newline.
character inserted MUST be a newline, but not the (new) document's final newline.
"|L-N" : Delete N characters from the source text, containing L newlines. The last
character inserted MUST be a newline, but not the (old) document's final newline.
"|L=N" : Keep N characters from the source text, containing L newlines. The last character

View file

@ -10,11 +10,11 @@
// favicon default name
// alternatively, set up a fully specified Url to your own favicon
"favicon": "favicon.ico",
//Ip and port which etherpad should bind at
"ip": "0.0.0.0",
"port" : 9001,
//The Type of the database. You can choose between dirty, postgres, sqlite and mysql
//You shouldn't use "dirty" for for anything else than testing or development
"dbType" : "dirty",
@ -22,38 +22,38 @@
"dbSettings" : {
"filename" : "var/dirty.db"
},
/* An Example of MySQL Configuration
"dbType" : "mysql",
"dbSettings" : {
"user" : "root",
"host" : "localhost",
"password": "",
"user" : "root",
"host" : "localhost",
"password": "",
"database": "store"
},
*/
//the default text of a pad
"defaultPadText" : "Welcome to Etherpad Lite!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n",
/* Users must have a session to access pads. This effectively allows only group pads to be accessed. */
"requireSession" : false,
/* Users may edit pads but not create new ones. Pad creation is only via the API. This applies both to group pads and regular pads. */
"editOnly" : false,
/* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly,
/* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly,
but makes it impossible to debug the javascript/css */
"minify" : true,
/* How long may clients use served javascript code (in seconds)? Without versioning this
may cause problems during deployment. Set to 0 to disable caching */
"maxAge" : 21600, // 60 * 60 * 6 = 6 hours
/* This is the path to the Abiword executable. Setting it to null, disables abiword.
Abiword is needed to enable the import/export of pads*/
Abiword is needed to enable the import/export of pads*/
"abiword" : null,
/* This setting is used if you require authentication of all users.
Note: /admin always requires authentication. */
"requireAuthentication": false,

View file

@ -16,7 +16,7 @@
{ "name": "admin", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/admin:expressCreateServer" } },
{ "name": "adminplugins", "hooks": {
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminplugins:expressCreateServer",
"socketio": "ep_etherpad-lite/node/hooks/express/adminplugins:socketio" }
"socketio": "ep_etherpad-lite/node/hooks/express/adminplugins:socketio" }
},
{ "name": "adminsettings", "hooks": {
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminsettings:expressCreateServer",

View file

@ -68,7 +68,7 @@ exports.listSessionsOfAuthor = sessionManager.listSessionsOfAuthor;
/************************/
/**
getText(padID, [rev]) returns the text of a pad
getText(padID, [rev]) returns the text of a pad
Example returns:
@ -83,7 +83,7 @@ exports.getText = function(padID, rev, callback)
callback = rev;
rev = undefined;
}
//check if rev is a number
if(rev !== undefined && typeof rev != "number")
{
@ -98,26 +98,26 @@ exports.getText = function(padID, rev, callback)
return;
}
}
//ensure this is not a negativ number
if(rev !== undefined && rev < 0)
{
callback(new customError("rev is a negativ number","apierror"));
return;
}
//ensure this is not a float value
if(rev !== undefined && !is_int(rev))
{
callback(new customError("rev is a float value","apierror"));
return;
}
//get the pad
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
//the client asked for a special revision
if(rev !== undefined)
{
@ -127,14 +127,14 @@ exports.getText = function(padID, rev, callback)
callback(new customError("rev is higher than the head revision of the pad","apierror"));
return;
}
//get the text of this revision
pad.getInternalRevisionAText(rev, function(err, atext)
{
if(ERR(err, callback)) return;
data = {text: atext.text};
callback(null, data);
})
}
@ -147,7 +147,7 @@ exports.getText = function(padID, rev, callback)
}
/**
setText(padID, text) sets the text of a pad
setText(padID, text) sets the text of a pad
Example returns:
@ -156,7 +156,7 @@ Example returns:
{code: 1, message:"text too long", data: null}
*/
exports.setText = function(padID, text, callback)
{
{
//text is required
if(typeof text != "string")
{
@ -168,17 +168,17 @@ exports.setText = function(padID, text, callback)
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
//set the text
pad.setText(text);
//update the clients on the pad
padMessageHandler.updatePadClients(pad, callback);
});
}
/**
getHTML(padID, [rev]) returns the html of a pad
getHTML(padID, [rev]) returns the html of a pad
Example returns:
@ -190,7 +190,7 @@ exports.getHTML = function(padID, rev, callback)
if(typeof rev == "function")
{
callback = rev;
rev = undefined;
rev = undefined;
}
if (rev !== undefined && typeof rev != "number")
@ -221,7 +221,7 @@ exports.getHTML = function(padID, rev, callback)
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
//the client asked for a special revision
if(rev !== undefined)
{
@ -231,8 +231,8 @@ exports.getHTML = function(padID, rev, callback)
callback(new customError("rev is higher than the head revision of the pad","apierror"));
return;
}
//get the html of this revision
//get the html of this revision
exportHtml.getPadHTML(pad, rev, function(err, html)
{
if(ERR(err, callback)) return;
@ -246,9 +246,9 @@ exports.getHTML = function(padID, rev, callback)
exportHtml.getPadHTML(pad, undefined, function (err, html)
{
if(ERR(err, callback)) return;
data = {html: html};
callback(null, data);
});
}
@ -276,7 +276,7 @@ exports.setHTML = function(padID, html, callback)
/*****************/
/**
getRevisionsCount(padID) returns the number of revisions of this pad
getRevisionsCount(padID) returns the number of revisions of this pad
Example returns:
@ -289,7 +289,7 @@ exports.getRevisionsCount = function(padID, callback)
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
callback(null, {revisions: pad.getHeadRevisionNumber()});
});
}
@ -316,7 +316,7 @@ exports.getLastEdited = function(padID, callback)
}
/**
createPad(padName [, text]) creates a new pad in this group
createPad(padName [, text]) creates a new pad in this group
Example returns:
@ -324,14 +324,14 @@ Example returns:
{code: 1, message:"pad does already exist", data: null}
*/
exports.createPad = function(padID, text, callback)
{
{
//ensure there is no $ in the padID
if(padID && padID.indexOf("$") != -1)
{
callback(new customError("createPad can't create group pads","apierror"));
return;
}
//create pad
getPadSafe(padID, false, text, function(err)
{
@ -341,7 +341,7 @@ exports.createPad = function(padID, text, callback)
}
/**
deletePad(padID) deletes a pad
deletePad(padID) deletes a pad
Example returns:
@ -353,13 +353,13 @@ exports.deletePad = function(padID, callback)
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
pad.remove(callback);
});
}
/**
getReadOnlyLink(padID) returns the read only link of a pad
getReadOnlyLink(padID) returns the read only link of a pad
Example returns:
@ -372,7 +372,7 @@ exports.getReadOnlyID = function(padID, callback)
getPadSafe(padID, true, function(err)
{
if(ERR(err, callback)) return;
//get the readonlyId
readOnlyManager.getReadOnlyId(padID, function(err, readOnlyId)
{
@ -383,7 +383,7 @@ exports.getReadOnlyID = function(padID, callback)
}
/**
setPublicStatus(padID, publicStatus) sets a boolean for the public status of a pad
setPublicStatus(padID, publicStatus) sets a boolean for the public status of a pad
Example returns:
@ -403,20 +403,20 @@ exports.setPublicStatus = function(padID, publicStatus, callback)
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
//convert string to boolean
if(typeof publicStatus == "string")
publicStatus = publicStatus == "true" ? true : false;
//set the password
pad.setPublicStatus(publicStatus);
callback();
});
}
/**
getPublicStatus(padID) return true of false
getPublicStatus(padID) return true of false
Example returns:
@ -431,18 +431,18 @@ exports.getPublicStatus = function(padID, callback)
callback(new customError("You can only get/set the publicStatus of pads that belong to a group","apierror"));
return;
}
//get the pad
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
callback(null, {publicStatus: pad.getPublicStatus()});
});
}
/**
setPassword(padID, password) returns ok or a error message
setPassword(padID, password) returns ok or a error message
Example returns:
@ -457,21 +457,21 @@ exports.setPassword = function(padID, password, callback)
callback(new customError("You can only get/set the password of pads that belong to a group","apierror"));
return;
}
//get the pad
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
//set the password
pad.setPassword(password == "" ? null : password);
callback();
});
}
/**
isPasswordProtected(padID) returns true or false
isPasswordProtected(padID) returns true or false
Example returns:
@ -491,13 +491,13 @@ exports.isPasswordProtected = function(padID, callback)
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
callback(null, {isPasswordProtected: pad.isPasswordProtected()});
});
}
/**
listAuthorsOfPad(padID) returns an array of authors who contributed to this pad
listAuthorsOfPad(padID) returns an array of authors who contributed to this pad
Example returns:
@ -510,7 +510,7 @@ exports.listAuthorsOfPad = function(padID, callback)
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
callback(null, {authorIDs: pad.getAllAuthors()});
});
}
@ -555,7 +555,7 @@ exports.sendClientsMessage = function (padID, msg, callback) {
//checks if a number is an int
function is_int(value)
{
{
return (parseFloat(value) == parseInt(value)) && !isNaN(value)
}
@ -574,19 +574,19 @@ function getPadSafe(padID, shouldExist, text, callback)
callback(new customError("padID is not a string","apierror"));
return;
}
//check if the padID maches the requirements
if(!padManager.isValidPadId(padID))
{
callback(new customError("padID did not match requirements","apierror"));
return;
}
//check if the pad exists
padManager.doesPadExists(padID, function(err, exists)
{
if(ERR(err, callback)) return;
//does not exist, but should
if(exists == false && shouldExist == true)
{

View file

@ -38,9 +38,9 @@ exports.doesAuthorExists = function (authorID, callback)
}
/**
* Returns the AuthorID for a token.
* @param {String} token The token
* @param {Function} callback callback (err, author)
* Returns the AuthorID for a token.
* @param {String} token The token
* @param {Function} callback callback (err, author)
*/
exports.getAuthor4Token = function (token, callback)
{
@ -53,21 +53,21 @@ exports.getAuthor4Token = function (token, callback)
}
/**
* Returns the AuthorID for a mapper.
* Returns the AuthorID for a mapper.
* @param {String} token The mapper
* @param {String} name The name of the author (optional)
* @param {Function} callback callback (err, author)
* @param {Function} callback callback (err, author)
*/
exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback)
{
mapAuthorWithDBKey("mapper2author", authorMapper, function(err, author)
{
if(ERR(err, callback)) return;
//set the name of this author
if(name)
exports.setAuthorName(author.authorID, name);
//return the authorID
callback(null, author);
});
@ -76,27 +76,27 @@ exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback)
/**
* Returns the AuthorID for a mapper. We can map using a mapperkey,
* so far this is token2author and mapper2author
* @param {String} mapperkey The database key name for this mapper
* @param {String} mapperkey The database key name for this mapper
* @param {String} mapper The mapper
* @param {Function} callback callback (err, author)
* @param {Function} callback callback (err, author)
*/
function mapAuthorWithDBKey (mapperkey, mapper, callback)
{
{
//try to map to an author
db.get(mapperkey + ":" + mapper, function (err, author)
{
if(ERR(err, callback)) return;
//there is no author with this mapper, so create one
if(author == null)
{
exports.createAuthor(null, function(err, author)
{
if(ERR(err, callback)) return;
//create the token2author relation
db.set(mapperkey + ":" + mapper, author.authorID);
//return the author
callback(null, author);
});
@ -106,7 +106,7 @@ function mapAuthorWithDBKey (mapperkey, mapper, callback)
{
//update the timestamp of this author
db.setSub("globalAuthor:" + author, ["timestamp"], new Date().getTime());
//return the author
callback(null, {authorID: author});
}
@ -114,20 +114,20 @@ function mapAuthorWithDBKey (mapperkey, mapper, callback)
}
/**
* Internal function that creates the database entry for an author
* @param {String} name The name of the author
* Internal function that creates the database entry for an author
* @param {String} name The name of the author
*/
exports.createAuthor = function(name, callback)
{
//create the new author name
var author = "a." + randomString(16);
//create the globalAuthors db entry
var authorObj = {"colorId" : Math.floor(Math.random()*32), "name": name, "timestamp": new Date().getTime()};
//set the global author db entry
db.set("globalAuthor:" + author, authorObj);
callback(null, {authorID: author});
}
@ -208,7 +208,7 @@ exports.listPadsOfAuthor = function (authorID, callback)
}
//everything is fine, return the pad IDs
else
{
{
var pads = [];
if(author.padIDs != null)
{
@ -234,16 +234,16 @@ exports.addPad = function (authorID, padID)
{
if(ERR(err)) return;
if(author == null) return;
//the entry doesn't exist so far, let's create it
if(author.padIDs == null)
{
author.padIDs = {};
}
//add the entry for this pad
author.padIDs[padID] = 1;// anything, because value is not used
//save the new element back
db.set("globalAuthor:" + authorID, author);
});
@ -260,11 +260,11 @@ exports.removePad = function (authorID, padID)
{
if(ERR(err)) return;
if(author == null) return;
if(author.padIDs != null)
{
//remove pad from author
delete author.padIDs[padID];
delete author.padIDs[padID];
db.set("globalAuthor:" + authorID, author);
}
});

View file

@ -1,5 +1,5 @@
/**
* The DB Module provides a database initalized with the settings
* The DB Module provides a database initalized with the settings
* provided by the settings module
*/
@ -33,14 +33,14 @@ exports.db = null;
/**
* Initalizes the database with the settings provided by the settings module
* @param {Function} callback
* @param {Function} callback
*/
exports.init = function(callback)
{
//initalize the database async
db.init(function(err)
{
//there was an error while initializing the database, output it and stop
//there was an error while initializing the database, output it and stop
if(err)
{
console.error("ERROR: Problem while initalizing the database");
@ -50,7 +50,7 @@ exports.init = function(callback)
//everything ok
else
{
exports.db = db;
exports.db = db;
callback(null);
}
});

View file

@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var ERR = require("async-stacktrace");
var customError = require("../utils/customError");
@ -30,13 +30,13 @@ var sessionManager = require("./SessionManager");
exports.listAllGroups = function(callback) {
db.get("groups", function (err, groups) {
if(ERR(err, callback)) return;
// there are no groups
if(groups == null) {
callback(null, {groupIDs: []});
return;
}
var groupIDs = [];
for ( var groupID in groups ) {
groupIDs.push(groupID);
@ -44,20 +44,20 @@ exports.listAllGroups = function(callback) {
callback(null, {groupIDs: groupIDs});
});
}
exports.deleteGroup = function(groupID, callback)
{
var group;
async.series([
//ensure group exists
//ensure group exists
function (callback)
{
//try to get the group entry
db.get("group:" + groupID, function (err, _group)
{
if(ERR(err, callback)) return;
//group does not exist
if(_group == null)
{
@ -80,14 +80,14 @@ exports.deleteGroup = function(groupID, callback)
{
padIDs.push(i);
}
//loop trough all pads and delete them
//loop trough all pads and delete them
async.forEach(padIDs, function(padID, callback)
{
padManager.getPad(padID, function(err, pad)
{
if(ERR(err, callback)) return;
pad.remove(callback);
});
}, callback);
@ -99,18 +99,18 @@ exports.deleteGroup = function(groupID, callback)
db.get("group2sessions:" + groupID, function (err, group2sessions)
{
if(ERR(err, callback)) return;
//skip if there is no group2sessions entry
if(group2sessions == null) {callback(); return}
//collect all sessions in an array, that allows us to use async.forEach
var sessions = [];
for(var i in group2sessions.sessionsIDs)
{
sessions.push(i);
}
//loop trough all sessions and delete them
//loop trough all sessions and delete them
async.forEach(sessions, function(session, callback)
{
sessionManager.deleteSession(session, callback);
@ -138,7 +138,7 @@ exports.deleteGroup = function(groupID, callback)
}
groups.splice(groups.indexOf(groupID), 1);
// store empty groupe list
if(groups.length == 0) {
db.set("groups", {});
@ -163,7 +163,7 @@ exports.deleteGroup = function(groupID, callback)
callback();
});
}
exports.doesGroupExist = function(groupID, callback)
{
//try to get the group entry
@ -178,17 +178,17 @@ exports.createGroup = function(callback)
{
//search for non existing groupID
var groupID = "g." + randomString(16);
//create the group
db.set("group:" + groupID, {pads: {}});
//list the group
exports.listAllGroups(function(err, groups) {
if(ERR(err, callback)) return;
groups = groups? groups.groupIDs : [];
groups.push(groupID);
// regenerate group list
var newGroups = {};
async.forEach(groups, function(group, cb) {
@ -209,22 +209,22 @@ exports.createGroupIfNotExistsFor = function(groupMapper, callback)
callback(new customError("groupMapper is no string","apierror"));
return;
}
//try to get a group for this mapper
db.get("mapper2group:"+groupMapper, function(err, groupID)
{
if(ERR(err, callback)) return;
//there is no group for this mapper, let's create a group
if(groupID == null)
{
exports.createGroup(function(err, responseObj)
{
if(ERR(err, callback)) return;
//create the mapper entry for this group
db.set("mapper2group:"+groupMapper, responseObj.groupID);
callback(null, responseObj);
});
}
@ -243,13 +243,13 @@ exports.createGroupPad = function(groupID, padName, text, callback)
var padID = groupID + "$" + padName;
async.series([
//ensure group exists
//ensure group exists
function (callback)
{
exports.doesGroupExist(groupID, function(err, exists)
{
if(ERR(err, callback)) return;
//group does not exist
if(exists == false)
{
@ -268,7 +268,7 @@ exports.createGroupPad = function(groupID, padName, text, callback)
padManager.doesPadExists(padID, function(err, exists)
{
if(ERR(err, callback)) return;
//pad exists already
if(exists == true)
{
@ -308,7 +308,7 @@ exports.listPads = function(groupID, callback)
exports.doesGroupExist(groupID, function(err, exists)
{
if(ERR(err, callback)) return;
//group does not exist
if(exists == false)
{

View file

@ -83,33 +83,33 @@ Pad.prototype.appendRevision = function appendRevision(aChangeset, author) {
db.set("pad:"+this.id+":revs:"+newRev, newRevData);
this.saveToDatabase();
// set the author to pad
if(author)
authorManager.addPad(author, this.id);
if (this.head == 0) {
hooks.callAll("padCreate", {'pad':this});
} else {
hooks.callAll("padUpdate", {'pad':this});
}
}
};
//save all attributes to the database
Pad.prototype.saveToDatabase = function saveToDatabase(){
var dbObject = {};
for(var attr in this){
if(typeof this[attr] === "function") continue;
if(attributeBlackList.indexOf(attr) !== -1) continue;
dbObject[attr] = this[attr];
if(jsonableList.indexOf(attr) !== -1){
dbObject[attr] = dbObject[attr].toJsonable();
}
}
db.set("pad:"+this.id, dbObject);
}
@ -510,7 +510,7 @@ Pad.prototype.addSavedRevision = function addSavedRevision(revNum, savedById, la
return;
}
}
//build the saved revision object
var savedRevision = {};
savedRevision.revNum = revNum;
@ -518,7 +518,7 @@ Pad.prototype.addSavedRevision = function addSavedRevision(revNum, savedById, la
savedRevision.label = label || "Revision " + revNum;
savedRevision.timestamp = new Date().getTime();
savedRevision.id = randomString(10);
//save this new saved revision
this.savedRevisions.push(savedRevision);
this.saveToDatabase();

View file

@ -23,7 +23,7 @@ var customError = require("../utils/customError");
var Pad = require("../db/Pad").Pad;
var db = require("./DB").db;
/**
/**
* An Object containing all known Pads. Provides "get" and "set" functions,
* which should be used instead of indexing with brackets. These prepend a
* colon to the key, to avoid conflicting with built-in Object methods or with
@ -50,24 +50,24 @@ var padIdTransforms = [
/**
* Returns a Pad Object with the callback
* @param id A String with the id of the pad
* @param {Function} callback
* @param {Function} callback
*/
exports.getPad = function(id, text, callback)
{
{
//check if this is a valid padId
if(!exports.isValidPadId(id))
{
callback(new customError(id + " is not a valid padId","apierror"));
return;
}
//make text an optional parameter
if(typeof text == "function")
{
callback = text;
text = null;
}
//check if this is a valid text
if(text != null)
{
@ -77,7 +77,7 @@ exports.getPad = function(id, text, callback)
callback(new customError("text is not a string","apierror"));
return;
}
//check if text is less than 100k chars
if(text.length > 100000)
{
@ -85,9 +85,9 @@ exports.getPad = function(id, text, callback)
return;
}
}
var pad = globalPads.get(id);
//return pad if its already loaded
if(pad != null)
{
@ -97,12 +97,12 @@ exports.getPad = function(id, text, callback)
else
{
pad = new Pad(id);
//initalize the pad
pad.init(text, function(err)
{
if(ERR(err, callback)) return;
globalPads.set(id, pad);
callback(null, pad);
});
@ -120,7 +120,7 @@ exports.doesPadExists = function(padId, callback)
}
else
{
callback(null, false);
callback(null, false);
}
});
}

View file

@ -29,9 +29,9 @@ var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
* @param {String} padId the id of the pad
*/
exports.getReadOnlyId = function (padId, callback)
{
{
var readOnlyId;
async.waterfall([
//check if there is a pad2readonly entry
function(callback)
@ -44,7 +44,7 @@ exports.getReadOnlyId = function (padId, callback)
if(dbReadOnlyId == null)
{
readOnlyId = "r." + randomString(16);
db.set("pad2readonly:" + padId, readOnlyId);
db.set("readonly2pad:" + readOnlyId, padId);
}
@ -53,7 +53,7 @@ exports.getReadOnlyId = function (padId, callback)
{
readOnlyId = dbReadOnlyId;
}
callback();
}
], function(err)

View file

@ -33,11 +33,11 @@ var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
* @param padID the pad the user wants to access
* @param sesssionID the session the user has (set via api)
* @param token the token of the author (randomly generated at client side, used for public pads)
* @param password the password the user has given to access this pad, can be null
* @param password the password the user has given to access this pad, can be null
* @param callback will be called with (err, {accessStatus: grant|deny|wrongPassword|needPassword, authorID: a.xxxxxx})
*/
*/
exports.checkAccess = function (padID, sessionCookie, token, password, callback)
{
{
var statusObject;
// a valid session is required (api-only mode)
@ -60,7 +60,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
authorManager.getAuthor4Token(token, function(err, author)
{
if(ERR(err, callback)) return;
// assume user has access
statusObject = {accessStatus: "grant", authorID: author};
// user can't create pads
@ -70,7 +70,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
padManager.doesPadExists(padID, function(err, exists)
{
if(ERR(err, callback)) return;
// pad doesn't exist - user can't have access
if(!exists) statusObject.accessStatus = "deny";
// grant or deny access, with author of token
@ -84,12 +84,12 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
callback(null, statusObject);
}
})
//don't continue
return;
}
}
var groupID = padID.split("$")[0];
var padExists = false;
var validSession = false;
@ -100,7 +100,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
var passwordStatus = password == null ? "notGiven" : "wrong"; // notGiven, correct, wrong
async.series([
//get basic informations from the database
//get basic informations from the database
function(callback)
{
async.parallel([
@ -121,27 +121,27 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
callback();
return;
}
var sessionIDs = sessionCookie.split(',');
async.forEach(sessionIDs, function(sessionID, callback) {
sessionManager.getSessionInfo(sessionID, function(err, sessionInfo) {
//skip session if it doesn't exist
if(err && err.message == "sessionID does not exist") return;
if(ERR(err, callback)) return;
var now = Math.floor(new Date().getTime()/1000);
//is it for this group?
if(sessionInfo.groupID != groupID) return;
//is validUntil still ok?
if(sessionInfo.validUntil <= now) return;
// There is a valid session
validSession = true;
sessionAuthor = sessionInfo.authorID;
callback();
});
}, callback);
@ -163,28 +163,28 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
function(callback)
{
//skip this if the pad doesn't exists
if(padExists == false)
if(padExists == false)
{
callback();
return;
}
padManager.getPad(padID, function(err, pad)
{
if(ERR(err, callback)) return;
//is it a public pad?
isPublic = pad.getPublicStatus();
//is it password protected?
isPasswordProtected = pad.isPasswordProtected();
//is password correct?
if(isPasswordProtected && password && pad.isCorrectPassword(password))
{
passwordStatus = "correct";
}
callback();
});
},
@ -221,7 +221,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
{
throw new Error("Ops, something wrong happend");
}
}
}
//- a valid session for this group avaible but pad doesn't exists
else if(validSession && !padExists)
{
@ -245,7 +245,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
//--> grant access, with author of token
statusObject = {accessStatus: "grant", authorID: tokenAuthor};
}
//- its public and the pad is password protected but wrong password given
//- its public and the pad is password protected but wrong password given
else if(isPublic && isPasswordProtected && passwordStatus == "wrong")
{
//--> deny access, ask for new password and tell them that the password is wrong
@ -267,14 +267,14 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
{
throw new Error("Ops, something wrong happend");
}
}
}
// there is no valid session avaiable AND pad doesn't exists
else
{
//--> deny access
statusObject = {accessStatus: "deny"};
}
callback();
}
], function(err)

View file

@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var ERR = require("async-stacktrace");
var customError = require("../utils/customError");
@ -26,7 +26,7 @@ var db = require("./DB").db;
var async = require("async");
var groupMangager = require("./GroupManager");
var authorMangager = require("./AuthorManager");
exports.doesSessionExist = function(sessionID, callback)
{
//check if the database entry of this session exists
@ -36,7 +36,7 @@ exports.doesSessionExist = function(sessionID, callback)
callback(null, session != null);
});
}
/**
* Creates a new session between an author and a group
*/
@ -51,7 +51,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
groupMangager.doesGroupExist(groupID, function(err, exists)
{
if(ERR(err, callback)) return;
//group does not exist
if(exists == false)
{
@ -70,7 +70,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
authorMangager.doesAuthorExists(authorID, function(err, exists)
{
if(ERR(err, callback)) return;
//author does not exist
if(exists == false)
{
@ -100,34 +100,34 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
return;
}
}
//ensure this is not a negativ number
if(validUntil < 0)
{
callback(new customError("validUntil is a negativ number","apierror"));
return;
}
//ensure this is not a float value
if(!is_int(validUntil))
{
callback(new customError("validUntil is a float value","apierror"));
return;
}
//check if validUntil is in the future
if(Math.floor(new Date().getTime()/1000) > validUntil)
{
callback(new customError("validUntil is in the past","apierror"));
return;
}
//generate sessionID
sessionID = "s." + randomString(16);
//set the session into the database
db.set("session:" + sessionID, {"groupID": groupID, "authorID": authorID, "validUntil": validUntil});
callback();
},
//set the group2sessions entry
@ -137,19 +137,19 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
db.get("group2sessions:" + groupID, function(err, group2sessions)
{
if(ERR(err, callback)) return;
//the entry doesn't exist so far, let's create it
if(group2sessions == null || group2sessions.sessionIDs == null)
{
group2sessions = {sessionIDs : {}};
}
//add the entry for this session
group2sessions.sessionIDs[sessionID] = 1;
//save the new element back
db.set("group2sessions:" + groupID, group2sessions);
callback();
});
},
@ -160,26 +160,26 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
db.get("author2sessions:" + authorID, function(err, author2sessions)
{
if(ERR(err, callback)) return;
//the entry doesn't exist so far, let's create it
if(author2sessions == null || author2sessions.sessionIDs == null)
{
author2sessions = {sessionIDs : {}};
}
//add the entry for this session
author2sessions.sessionIDs[sessionID] = 1;
//save the new element back
db.set("author2sessions:" + authorID, author2sessions);
callback();
});
}
], function(err)
{
if(ERR(err, callback)) return;
//return error and sessionID
callback(null, {sessionID: sessionID});
})
@ -191,7 +191,7 @@ exports.getSessionInfo = function(sessionID, callback)
db.get("session:" + sessionID, function (err, session)
{
if(ERR(err, callback)) return;
//session does not exists
if(session == null)
{
@ -220,7 +220,7 @@ exports.deleteSession = function(sessionID, callback)
db.get("session:" + sessionID, function (err, session)
{
if(ERR(err, callback)) return;
//session does not exists
if(session == null)
{
@ -231,7 +231,7 @@ exports.deleteSession = function(sessionID, callback)
{
authorID = session.authorID;
groupID = session.groupID;
callback();
}
});
@ -261,15 +261,15 @@ exports.deleteSession = function(sessionID, callback)
{
//remove the session
db.remove("session:" + sessionID);
//remove session from group2sessions
delete group2sessions.sessionIDs[sessionID];
db.set("group2sessions:" + groupID, group2sessions);
//remove session from author2sessions
delete author2sessions.sessionIDs[sessionID];
db.set("author2sessions:" + authorID, author2sessions);
callback();
}
], function(err)
@ -284,7 +284,7 @@ exports.listSessionsOfGroup = function(groupID, callback)
groupMangager.doesGroupExist(groupID, function(err, exists)
{
if(ERR(err, callback)) return;
//group does not exist
if(exists == false)
{
@ -299,11 +299,11 @@ exports.listSessionsOfGroup = function(groupID, callback)
}
exports.listSessionsOfAuthor = function(authorID, callback)
{
{
authorMangager.doesAuthorExists(authorID, function(err, exists)
{
if(ERR(err, callback)) return;
//group does not exist
if(exists == false)
{
@ -334,14 +334,14 @@ function listSessionsWithDBKey (dbkey, callback)
});
},
function(callback)
{
{
//collect all sessionIDs in an arrary
var sessionIDs = [];
for (var i in sessions)
{
sessionIDs.push(i);
}
//foreach trough the sessions and get the sessioninfos
async.forEach(sessionIDs, function(sessionID, callback)
{
@ -362,6 +362,6 @@ function listSessionsWithDBKey (dbkey, callback)
//checks if a number is an int
function is_int(value)
{
{
return (parseFloat(value) == parseInt(value)) && !isNaN(value)
}

View file

@ -120,7 +120,7 @@ exports.require = function (name, args, mod) {
args.e = exports;
args.require = require;
var template = '<% e._init(buf); %>' + fs.readFileSync(ejspath).toString() + '<% e._exit(); %>';
exports.info.args.push(args);
exports.info.file_stack.push({path: ejspath, inherit: []});

View file

@ -31,7 +31,7 @@ try
{
apikey = fs.readFileSync("./APIKEY.txt","utf8");
}
catch(e)
catch(e)
{
apikey = randomString(32);
fs.writeFileSync("./APIKEY.txt",apikey,"utf8");
@ -124,7 +124,7 @@ exports.handle = function(apiVersion, functionName, fields, req, res)
break;
}
}
//say goodbye if this is an unkown API version
if(!isKnownApiVersion)
{
@ -132,7 +132,7 @@ exports.handle = function(apiVersion, functionName, fields, req, res)
res.send({code: 3, message: "no such api version", data: null});
return;
}
//check if this is a valid function name
var isKnownFunctionname = false;
for(var knownFunctionname in version[apiVersion])
@ -143,14 +143,14 @@ exports.handle = function(apiVersion, functionName, fields, req, res)
break;
}
}
//say goodbye if this is a unkown function
if(!isKnownFunctionname)
{
res.send({code: 3, message: "no such function", data: null});
return;
}
//check the api key!
if(fields["apikey"] != apikey.trim())
{
@ -190,16 +190,16 @@ function callAPI(apiVersion, functionName, fields, req, res)
{
functionParams.push(fields[ version[apiVersion][functionName][i] ]);
}
//add a callback function to handle the response
functionParams.push(function(err, data)
{
{
// no error happend, everything is fine
if(err == null)
{
if(!data)
data = null;
res.send({code: 0, message: "ok", data: data});
}
// parameters were wrong and the api stopped execution, pass the error
@ -214,7 +214,7 @@ function callAPI(apiVersion, functionName, fields, req, res)
ERR(err);
}
});
//call the api function
api[functionName](functionParams[0],functionParams[1],functionParams[2],functionParams[3],functionParams[4]);
}

View file

@ -33,15 +33,15 @@ if(settings.abiword != null)
var tempDirectory = "/tmp";
//tempDirectory changes if the operating system is windows
//tempDirectory changes if the operating system is windows
if(os.type().indexOf("Windows") > -1)
{
tempDirectory = process.env.TEMP;
}
/**
* do a requested export
*/
*/
exports.doExport = function(req, res, padId, type)
{
//tell the browser that this is a downloadable file
@ -100,7 +100,7 @@ exports.doExport = function(req, res, padId, type)
if(ERR(err, callback)) return;
html = _html;
callback();
});
});
},
//decide what to do with the html export
function(callback)
@ -109,13 +109,13 @@ exports.doExport = function(req, res, padId, type)
if(type == "html")
{
res.send(html);
callback("stop");
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);
fs.writeFile(srcFile, html, callback);
}
},
//send the convert job to abiword
@ -123,7 +123,7 @@ exports.doExport = function(req, res, padId, type)
{
//ensure html can be collected by the garbage collector
html = null;
destFile = tempDirectory + "/eplite_export_" + randNum + "." + type;
abiword.convertFile(srcFile, destFile, type, callback);
},
@ -145,7 +145,7 @@ exports.doExport = function(req, res, padId, type)
//100ms delay to accomidate for slow windows fs
if(os.type().indexOf("Windows") > -1)
{
setTimeout(function()
setTimeout(function()
{
fs.unlink(destFile, callback);
}, 100);

View file

@ -38,20 +38,20 @@ if(os.type().indexOf("Windows") > -1)
{
tempDirectory = process.env.TEMP;
}
/**
* 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)
@ -59,9 +59,9 @@ exports.doImport = function(req, res, padId)
var form = new formidable.IncomingForm();
form.keepExtensions = true;
form.uploadDir = tempDirectory;
form.parse(req, function(err, fields, files)
{
form.parse(req, function(err, fields, files)
{
//the upload failed, stop at this point
if(err || files.file === undefined)
{
@ -69,7 +69,7 @@ exports.doImport = function(req, res, padId)
callback("uploadFailed");
}
//everything ok, continue
else
else
{
//save the path of the uploaded file
srcFile = files.file.path;
@ -77,14 +77,14 @@ exports.doImport = function(req, res, padId)
}
});
},
//ensure this is a file ending we know, else we change the file ending to .txt
//this allows us to accept source code files like .c or .java
function(callback)
{
var fileEnding = (srcFile.split(".")[1] || "").toLowerCase();
var knownFileEndings = ["txt", "doc", "docx", "pdf", "odt", "html", "htm"];
//find out if this is a known file ending
var fileEndingKnown = false;
for(var i in knownFileEndings)
@ -94,7 +94,7 @@ exports.doImport = function(req, res, padId)
fileEndingKnown = true;
}
}
//if the file ending is known, continue as normal
if(fileEndingKnown)
{
@ -105,11 +105,11 @@ exports.doImport = function(req, res, padId)
{
var oldSrcFile = srcFile;
srcFile = srcFile.split(".")[0] + ".txt";
fs.rename(oldSrcFile, srcFile, callback);
}
},
//convert file to text
function(callback)
{
@ -125,7 +125,7 @@ exports.doImport = function(req, res, padId)
}
});
},
//get the pad object
function(callback)
{
@ -136,7 +136,7 @@ exports.doImport = function(req, res, padId)
callback();
});
},
//read the text
function(callback)
{
@ -144,8 +144,8 @@ exports.doImport = function(req, res, padId)
{
if(ERR(err, callback)) return;
text = _text;
//node on windows has a delay on releasing of the file lock.
//node on windows has a delay on releasing of the file lock.
//We add a 100ms delay to work around this
if(os.type().indexOf("Windows") > -1)
{
@ -160,14 +160,14 @@ exports.doImport = function(req, res, padId)
}
});
},
//change text of the pad and broadcast the changeset
function(callback)
{
pad.setText(text);
padMessageHandler.updatePadClients(pad, callback);
},
//clean up temporary files
function(callback)
{
@ -185,7 +185,7 @@ exports.doImport = function(req, res, padId)
], function(err)
{
var status = "ok";
//check for known errors and replace the status
if(err == "uploadFailed" || err == "convertFailed")
{
@ -194,7 +194,7 @@ exports.doImport = function(req, res, padId)
}
ERR(err);
//close the connection
res.send("<script type='text/javascript' src='/static/js/jquery.js'></script><script> if ( (!$.browser.msie) && (!($.browser.mozilla && $.browser.version.indexOf(\"1.8.\") == 0)) ){document.domain = document.domain;}var impexp = window.top.require('/pad_impexp').padimpexp.handleFrameCall('" + status + "');</script>", 200);
});

View file

@ -1,6 +1,6 @@
/**
* The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions
*/
* The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions
*/
/*
* Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
@ -71,7 +71,7 @@ exports.setSocketIO = function(socket_io)
* @param client the new client
*/
exports.handleConnect = function(client)
{
{
//Initalize sessioninfos for this new session
sessioninfos[client.id]={};
}
@ -98,20 +98,20 @@ exports.kickSessionsFromPad = function(padID)
* @param client the client that leaves
*/
exports.handleDisconnect = function(client)
{
{
//save the padname of this session
var sessionPad=sessioninfos[client.id].padId;
//if this connection was already etablished with a handshake, send a disconnect message to the others
if(sessioninfos[client.id] && sessioninfos[client.id].author)
{
var author = sessioninfos[client.id].author;
//get the author color out of the db
authorManager.getAuthorColorId(author, function(err, color)
{
ERR(err);
//prepare the notification for the other users on the pad, that this user left
var messageToTheOtherUsers = {
"type": "COLLABROOM",
@ -125,7 +125,7 @@ exports.handleDisconnect = function(client)
}
}
};
//Go trough all user that are still on the pad, and send them the USER_LEAVE message
for(i in pad2sessions[sessionPad])
{
@ -133,23 +133,23 @@ exports.handleDisconnect = function(client)
if(socket !== undefined){
socket.json.send(messageToTheOtherUsers);
}
}
});
});
}
//Go trough all sessions of this pad, search and destroy the entry of this client
for(i in pad2sessions[sessionPad])
{
if(pad2sessions[sessionPad][i] == client.id)
{
pad2sessions[sessionPad].splice(i, 1);
pad2sessions[sessionPad].splice(i, 1);
break;
}
}
//Delete the sessioninfos entrys of this session
delete sessioninfos[client.id];
delete sessioninfos[client.id];
}
/**
@ -158,7 +158,7 @@ exports.handleDisconnect = function(client)
* @param message the message from the client
*/
exports.handleMessage = function(client, message)
{
{
if(message == null)
{
@ -173,18 +173,18 @@ exports.handleMessage = function(client, message)
var handleMessageHook = function(callback){
var dropMessage = false;
// Call handleMessage hook. If a plugin returns null, the message will be dropped. Note that for all messages
// Call handleMessage hook. If a plugin returns null, the message will be dropped. Note that for all messages
// handleMessage will be called, even if the client is not authorized
hooks.aCallAll("handleMessage", { client: client, message: message }, function ( err, messages ) {
if(ERR(err, callback)) return;
_.each(messages, function(newMessage){
if ( newMessage === null ) {
dropMessage = true;
}
});
// If no plugins explicitly told us to drop the message, its ok to proceed
if(!dropMessage){ callback() };
});
@ -224,7 +224,7 @@ exports.handleMessage = function(client, message)
//check permissions
function(callback)
{
if(!message.padId){
// If the message has a padId we assume the client is already known to the server and needs no re-authorization
callback();
@ -265,11 +265,11 @@ exports.handleMessage = function(client, message)
function handleSaveRevisionMessage(client, message){
var padId = sessioninfos[client.id].padId;
var userId = sessioninfos[client.id].author;
padManager.getPad(padId, function(err, pad)
{
if(ERR(err)) return;
pad.addSavedRevision(pad.head, userId);
});
}
@ -307,10 +307,10 @@ function handleChatMessage(client, message)
var userId = sessioninfos[client.id].author;
var text = message.data.text;
var padId = sessioninfos[client.id].padId;
var pad;
var userName;
async.series([
//get the pad
function(callback)
@ -336,7 +336,7 @@ function handleChatMessage(client, message)
{
//save the chat message
pad.appendChatMessage(text, userId, time);
var msg = {
type: "COLLABROOM",
data: {
@ -347,13 +347,13 @@ function handleChatMessage(client, message)
text: text
}
};
//broadcast the chat message to everyone on the pad
for(var i in pad2sessions[padId])
{
socketio.sockets.sockets[pad2sessions[padId][i]].json.send(msg);
}
callback();
}
], function(err)
@ -381,9 +381,9 @@ function handleSuggestUserName(client, message)
messageLogger.warn("Dropped message, suggestUserName Message has no unnamedId!");
return;
}
var padId = sessioninfos[client.id].padId;
//search the author and send him this message
for(var i in pad2sessions[padId])
{
@ -408,14 +408,14 @@ function handleUserInfoUpdate(client, message)
messageLogger.warn("Dropped message, USERINFO_UPDATE Message has no colorId!");
return;
}
//Find out the author name of this session
var author = sessioninfos[client.id].author;
//Tell the authorManager about the new attributes
authorManager.setAuthorColorId(author, message.data.userInfo.colorId);
authorManager.setAuthorName(author, message.data.userInfo.name);
var padId = sessioninfos[client.id].padId;
var infoMsg = {
@ -432,13 +432,13 @@ function handleUserInfoUpdate(client, message)
}
}
};
//set a null name, when there is no name set. cause the client wants it null
if(infoMsg.data.userInfo.name == null)
{
infoMsg.data.userInfo.name = null;
}
//Send the other clients on the pad the update message
for(var i in pad2sessions[padId])
{
@ -481,7 +481,7 @@ function handleUserChanges(client, message)
messageLogger.warn("Dropped message, USER_CHANGES Message has no changeset!");
return;
}
//get all Vars we need
var baseRev = message.data.baseRev;
var wireApool = (new AttributePool()).fromJsonable(message.data.apool);
@ -489,9 +489,9 @@ function handleUserChanges(client, message)
// The client might disconnect between our callbacks. We should still
// finish processing the changeset, so keep a reference to the session.
var thisSession = sessioninfos[client.id];
var r, apool, pad;
async.series([
//get the pad
function(callback)
@ -507,7 +507,7 @@ function handleUserChanges(client, message)
function(callback)
{
//ex. _checkChangesetAndPool
try
{
// Verify that the changeset has valid syntax and is in canonical form
@ -528,12 +528,12 @@ function handleUserChanges(client, message)
client.json.send({disconnect:"badChangeset"});
return;
}
//ex. adoptChangesetAttribs
//Afaik, it copies the new attributes from the changeset, to the global Attribute Pool
changeset = Changeset.moveOpsToNewPool(changeset, wireApool, pad.pool);
//ex. applyUserChanges
apool = pad.pool;
r = baseRev;
@ -547,7 +547,7 @@ function handleUserChanges(client, message)
function(callback)
{
r++;
pad.getRevisionChangeset(r, function(err, c)
{
if(ERR(err, callback)) return;
@ -573,17 +573,17 @@ function handleUserChanges(client, message)
function (callback)
{
var prevText = pad.text();
if (Changeset.oldLen(changeset) != prevText.length)
if (Changeset.oldLen(changeset) != prevText.length)
{
console.warn("Can't apply USER_CHANGES "+changeset+" with oldLen " + Changeset.oldLen(changeset) + " to document of length " + prevText.length);
client.json.send({disconnect:"badChangeset"});
callback();
return;
}
pad.appendRevision(changeset, thisSession.author);
var correctionChangeset = _correctMarkersInPad(pad.atext, pad.pool);
if (correctionChangeset) {
pad.appendRevision(correctionChangeset);
@ -594,7 +594,7 @@ function handleUserChanges(client, message)
var nlChangeset = Changeset.makeSplice(pad.text(), pad.text().length-1, 0, "\n");
pad.appendRevision(nlChangeset);
}
exports.updatePadClients(pad, callback);
}
], function(err)
@ -604,14 +604,14 @@ function handleUserChanges(client, message)
}
exports.updatePadClients = function(pad, callback)
{
{
//skip this step if noone is on this pad
if(!pad2sessions[pad.id])
{
callback();
return;
}
//go trough all sessions on this pad
async.forEach(pad2sessions[pad.id], function(session, callback)
{
@ -621,10 +621,10 @@ exports.updatePadClients = function(pad, callback)
async.whilst(
function (){ return sessioninfos[session].rev < pad.getHeadRevisionNumber()},
function(callback)
{
{
var author, revChangeset, currentTime;
var r = sessioninfos[session].rev + 1;
async.parallel([
function (callback)
{
@ -677,8 +677,8 @@ exports.updatePadClients = function(pad, callback)
author: author,
currentTime: currentTime,
timeDelta: currentTime - sessioninfos[session].time
}};
}};
socketio.sockets.sockets[session].json.send(wireMsg);
}
@ -687,13 +687,13 @@ exports.updatePadClients = function(pad, callback)
sessioninfos[session].time = currentTime;
sessioninfos[session].rev = r;
}
callback(null);
});
},
callback
);
},callback);
},callback);
}
/**
@ -709,11 +709,11 @@ function _correctMarkersInPad(atext, apool) {
var offset = 0;
while (iter.hasNext()) {
var op = iter.next();
var hasMarker = _.find(AttributeManager.lineAttributes, function(attribute){
return Changeset.opAttributeValue(op, attribute, apool);
}) !== undefined;
if (hasMarker) {
for(var i=0;i<op.chars;i++) {
if (offset > 0 && text.charAt(offset-1) != '\n') {
@ -743,7 +743,7 @@ function _correctMarkersInPad(atext, apool) {
}
/**
* Handles a CLIENT_READY. A CLIENT_READY is the first message from the client to the server. The Client sends his token
* Handles a CLIENT_READY. A CLIENT_READY is the first message from the client to the server. The Client sends his token
* and the pad it wants to enter. The Server answers with the inital values (clientVars) of the pad
* @param client the client that send this message
* @param message the message from the client
@ -802,7 +802,7 @@ function handleClientReady(client, message)
securityManager.checkAccess (padIds.padId, message.sessionID, message.token, message.password, function(err, statusObject)
{
if(ERR(err, callback)) return;
//access was granted
if(statusObject.accessStatus == "grant")
{
@ -815,7 +815,7 @@ function handleClientReady(client, message)
client.json.send({accessStatus: statusObject.accessStatus})
}
});
},
},
//get all authordata of this new user
function(callback)
{
@ -855,7 +855,7 @@ function handleClientReady(client, message)
function(callback)
{
var authors = pad.getAllAuthors();
async.parallel([
//get timestamp of latest revission needed for timeslider
function(callback)
@ -892,7 +892,7 @@ function handleClientReady(client, message)
});
}
], callback);
},
function(callback)
{
@ -915,27 +915,27 @@ function handleClientReady(client, message)
}
}
}
//Save in sessioninfos that this session belonges to this pad
sessioninfos[client.id].padId = padIds.padId;
sessioninfos[client.id].readOnlyPadId = padIds.readOnlyPadId;
sessioninfos[client.id].readonly = padIds.readonly;
//check if there is already a pad2sessions entry, if not, create one
if(!pad2sessions[padIds.padId])
{
pad2sessions[padIds.padId] = [];
}
//Saves in pad2sessions that this session belongs to this pad
pad2sessions[padIds.padId].push(client.id);
//prepare all values for the wire
var atext = Changeset.cloneAText(pad.atext);
var attribsForWire = Changeset.prepareForWire(atext.attribs, pad.pool);
var apool = attribsForWire.pool.toJsonable();
atext.attribs = attribsForWire.translated;
// Warning: never ever send padIds.padId to the client. If the
// client is read only you would open a security hole 1 swedish
// mile wide...
@ -978,7 +978,7 @@ function handleClientReady(client, message)
"fullWidth": false,
"hideSidebar": false
},
"abiwordAvailable": settings.abiwordAvailable(),
"abiwordAvailable": settings.abiwordAvailable(),
"plugins": {
"plugins": plugins.plugins,
"parts": plugins.parts,
@ -992,7 +992,7 @@ function handleClientReady(client, message)
{
clientVars.userName = authorName;
}
//If this is a reconnect, we don't have to send the client the ClientVars again
if(message.reconnect == true)
{
@ -1007,9 +1007,9 @@ function handleClientReady(client, message)
//Save the current revision in sessioninfos, should be the same as in clientVars
sessioninfos[client.id].rev = pad.getHeadRevisionNumber();
}
sessioninfos[client.id].author = author;
//prepare the notification for the other users on the pad, that this user joined
var messageToTheOtherUsers = {
"type": "COLLABROOM",
@ -1023,19 +1023,19 @@ function handleClientReady(client, message)
}
}
};
//Add the authorname of this new User, if avaiable
if(authorName != null)
{
messageToTheOtherUsers.data.userInfo.name = authorName;
}
//Run trough all sessions of this pad
async.forEach(pad2sessions[padIds.padId], function(sessionID, callback)
{
var author, socket, sessionAuthorName, sessionAuthorColorId;
//Since sessioninfos might change while being enumerated, check if the
//Since sessioninfos might change while being enumerated, check if the
//sessionID is still assigned to a valid session
if(sessioninfos[sessionID] !== undefined &&
socketio.sockets.sockets[sessionID] !== undefined){
@ -1070,7 +1070,7 @@ function handleClientReady(client, message)
})
}
],callback);
},
},
function (callback)
{
//Jump over, if this session is the connection session
@ -1078,7 +1078,7 @@ function handleClientReady(client, message)
{
//Send this Session the Notification about the new user
socket.json.send(messageToTheOtherUsers);
//Send the new User a Notification about this other user
var messageToNotifyTheClientAboutTheOthers = {
"type": "COLLABROOM",
@ -1096,7 +1096,7 @@ function handleClientReady(client, message)
client.json.send(messageToNotifyTheClientAboutTheOthers);
}
}
], callback);
], callback);
}, callback);
}
],function(err)
@ -1106,7 +1106,7 @@ function handleClientReady(client, message)
}
/**
* Handles a request for a rough changeset, the timeslider client needs it
* Handles a request for a rough changeset, the timeslider client needs it
*/
function handleChangesetRequest(client, message)
{
@ -1136,7 +1136,7 @@ function handleChangesetRequest(client, message)
messageLogger.warn("Dropped message, changeset request has no requestID!");
return;
}
var granularity = message.data.granularity;
var start = message.data.start;
var end = start + (100 * granularity);
@ -1180,47 +1180,47 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
var composedChangesets = {};
var revisionDate = [];
var lines;
async.series([
//get the pad from the database
function(callback)
{
padManager.getPad(padId, function(err, _pad)
{
{
if(ERR(err, callback)) return;
pad = _pad;
callback();
});
},
function(callback)
{
{
//calculate the last full endnum
var lastRev = pad.getHeadRevisionNumber();
if (endNum > lastRev+1) {
endNum = lastRev+1;
}
endNum = Math.floor(endNum / granularity)*granularity;
var compositesChangesetNeeded = [];
var revTimesNeeded = [];
//figure out which composite Changeset and revTimes we need, to load them in bulk
var compositeStart = startNum;
while (compositeStart < endNum)
while (compositeStart < endNum)
{
var compositeEnd = compositeStart + granularity;
//add the composite Changeset we needed
compositesChangesetNeeded.push({start: compositeStart, end: compositeEnd});
//add the t1 time we need
revTimesNeeded.push(compositeStart == 0 ? 0 : compositeStart - 1);
//add the t2 time we need
revTimesNeeded.push(compositeEnd - 1);
compositeStart += granularity;
}
//get all needed db values parallel
async.parallel([
function(callback)
@ -1257,58 +1257,58 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
if(ERR(err, callback)) return;
lines = _lines;
callback();
});
});
}
], callback);
},
//doesn't know what happens here excatly :/
function(callback)
{
{
var compositeStart = startNum;
while (compositeStart < endNum)
while (compositeStart < endNum)
{
if (compositeStart + granularity > endNum)
if (compositeStart + granularity > endNum)
{
break;
}
var compositeEnd = compositeStart + granularity;
var forwards = composedChangesets[compositeStart + "/" + compositeEnd];
var backwards = Changeset.inverse(forwards, lines.textlines, lines.alines, pad.apool());
Changeset.mutateAttributionLines(forwards, lines.alines, pad.apool());
Changeset.mutateTextLines(forwards, lines.textlines);
var forwards2 = Changeset.moveOpsToNewPool(forwards, pad.apool(), apool);
var backwards2 = Changeset.moveOpsToNewPool(backwards, pad.apool(), apool);
var t1, t2;
if (compositeStart == 0)
if (compositeStart == 0)
{
t1 = revisionDate[0];
}
else
else
{
t1 = revisionDate[compositeStart - 1];
}
t2 = revisionDate[compositeEnd - 1];
timeDeltas.push(t2 - t1);
forwardsChangesets.push(forwards2);
backwardsChangesets.push(backwards2);
compositeStart += granularity;
}
callback();
}
], function(err)
{
if(ERR(err, callback)) return;
callback(null, {forwardsChangesets: forwardsChangesets,
backwardsChangesets: backwardsChangesets,
apool: apool.toJsonable(),
@ -1323,7 +1323,7 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
* Tries to rebuild the getPadLines function of the original Etherpad
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L263
*/
function getPadLines(padId, revNum, callback)
function getPadLines(padId, revNum, callback)
{
var atext;
var result = {};
@ -1334,7 +1334,7 @@ function getPadLines(padId, revNum, callback)
function(callback)
{
padManager.getPad(padId, function(err, _pad)
{
{
if(ERR(err, callback)) return;
pad = _pad;
callback();
@ -1396,14 +1396,14 @@ function composePadChangesets(padId, startNum, endNum, callback)
function(callback)
{
var changesetsNeeded=[];
//create a array for all changesets, we will
//create a array for all changesets, we will
//replace the values with the changeset later
for(var r=startNum;r<endNum;r++)
{
changesetsNeeded.push(r);
}
//get all changesets
async.forEach(changesetsNeeded, function(revNum,callback)
{
@ -1420,13 +1420,13 @@ function composePadChangesets(padId, startNum, endNum, callback)
{
changeset = changesets[startNum];
var pool = pad.apool();
for(var r=startNum+1;r<endNum;r++)
{
var cs = changesets[r];
changeset = Changeset.compose(changeset, cs, pool);
}
callback(null);
}
],

View file

@ -1,5 +1,5 @@
/**
* This is the Socket.IO Router. It routes the Messages between the
* This is the Socket.IO Router. It routes the Messages between the
* components of the Server. The components are at the moment: pad and timeslider
*/
@ -28,11 +28,11 @@ var securityManager = require("../db/SecurityManager");
* Saves all components
* key is the component name
* value is the component module
*/
*/
var components = {};
var socket;
/**
* adds a component
*/
@ -40,7 +40,7 @@ exports.addComponent = function(moduleName, module)
{
//save the component
components[moduleName] = module;
//give the module the socket
module.setSocketIO(socket);
}
@ -52,11 +52,11 @@ exports.setSocketIO = function(_socket)
{
//save this socket internaly
socket = _socket;
socket.sockets.on('connection', function(client)
{
var clientAuthorized = false;
//wrap the original send function to log the messages
client._send = client.send;
client.send = function(message)
@ -64,19 +64,19 @@ exports.setSocketIO = function(_socket)
messageLogger.info("to " + client.id + ": " + stringifyWithoutPassword(message));
client._send(message);
}
//tell all components about this connect
for(var i in components)
{
components[i].handleConnect(client);
}
//try to handle the message of this client
function handleMessage(message)
{
if(message.component && components[message.component])
{
//check if component is registered in the components array
//check if component is registered in the components array
if(components[message.component])
{
messageLogger.info("from " + client.id + ": " + stringifyWithoutPassword(message));
@ -87,8 +87,8 @@ exports.setSocketIO = function(_socket)
{
messageLogger.error("Can't route the message:" + stringifyWithoutPassword(message));
}
}
}
client.on('message', function(message)
{
if(message.protocolVersion && message.protocolVersion != 2)
@ -111,7 +111,7 @@ exports.setSocketIO = function(_socket)
securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject)
{
ERR(err);
//access was granted, mark the client as authorized and handle the message
if(statusObject.accessStatus == "grant")
{
@ -150,7 +150,7 @@ exports.setSocketIO = function(_socket)
function stringifyWithoutPassword(message)
{
var newMessage = {};
for(var i in message)
{
if(i == "password" && message[i] != null)
@ -158,6 +158,6 @@ function stringifyWithoutPassword(message)
else
newMessage[i]=message[i];
}
return JSON.stringify(newMessage);
}

View file

@ -22,7 +22,7 @@ exports.createServer = function () {
version = version.substring(0, 7);
console.log("Your Etherpad Lite git version is " + version);
}
catch(e)
catch(e)
{
console.warn("Can't get git version for server header\n" + e.message)
}

View file

@ -44,7 +44,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//The Etherpad client side sends information about how a disconnect happen
args.app.post('/ep/pad/connection-diagnostic-info', function(req, res) {
new formidable.IncomingForm().parse(req, function(err, fields, files) {
new formidable.IncomingForm().parse(req, function(err, fields, files) {
console.log("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
res.end("OK");
});
@ -52,7 +52,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//The Etherpad client side sends information about client side javscript errors
args.app.post('/jserror', function(req, res) {
new formidable.IncomingForm().parse(req, function(err, fields, files) {
new formidable.IncomingForm().parse(req, function(err, fields, files) {
console.error("CLIENT SIDE JAVASCRIPT ERROR: " + fields.errorInfo);
res.end("OK");
});

View file

@ -31,7 +31,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//if abiword is disabled, skip handling this request
if(settings.abiword == null) {
next();
return;
return;
}
hasPadAccess(req, res, function() {

View file

@ -7,7 +7,7 @@ var exporthtml = require("../../utils/ExportHtml");
exports.expressCreateServer = function (hook_name, args, cb) {
//serve read only pad
args.app.get('/ro/:id', function(req, res)
{
{
var html;
var padId;
var pad;
@ -22,8 +22,8 @@ exports.expressCreateServer = function (hook_name, args, cb) {
padId = _padId;
//we need that to tell hasPadAcess about the pad
req.params.pad = padId;
//we need that to tell hasPadAcess about the pad
req.params.pad = padId;
callback();
});

View file

@ -8,7 +8,7 @@ var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess");
var padMessageHandler = require("../../handler/PadMessageHandler");
var connect = require('connect');
exports.expressCreateServer = function (hook_name, args, cb) {
//init socket.io and redirect all requests to the MessageHandler
var io = socketio.listen(args.server);
@ -36,7 +36,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
});
});
// the following has been successfully tested with the following browsers
// the following has been successfully tested with the following browsers
// works also behind reverse proxy
// Firefox 14.0.1
// IE8 with Native XMLHTTP support
@ -49,7 +49,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
debug: function (str)
{
socketIOLogger.debug.apply(socketIOLogger, arguments);
},
},
info: function (str)
{
socketIOLogger.info.apply(socketIOLogger, arguments);

View file

@ -26,7 +26,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//serve pad.html under /p
args.app.get('/p/:pad', function(req, res, next)
{
{
res.send(eejs.require("ep_etherpad-lite/templates/pad.html", {req: req}));
});

View file

@ -41,9 +41,9 @@ exports.expressCreateServer = function (hook_name, args, cb) {
var clientParts = _(plugins.parts)
.filter(function(part){ return _(part).has('client_hooks') });
var clientPlugins = {};
_(clientParts).chain()
.map(function(part){ return part.plugin })
.uniq()
@ -51,7 +51,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
clientPlugins[name] = _(plugins.plugins[name]).clone();
delete clientPlugins[name]['package'];
});
res.header("Content-Type","application/json; charset=utf-8");
res.write(JSON.stringify({"plugins": clientPlugins, "parts": clientParts}));
res.end();

View file

@ -75,7 +75,7 @@ exports.basicAuth = function (req, res, next) {
Note that the process could stop already in step 3 with a redirect to login page.
*/
authorize(function (ok) {
if (ok) return next();
authenticate(function (ok) {
@ -105,7 +105,7 @@ exports.expressConfigure = function (hook_name, args, cb) {
exports.sessionStore = new express.session.MemoryStore();
exports.secret = randomString(32);
}
args.app.use(express.cookieParser(exports.secret));
args.app.sessionStore = exports.sessionStore;

View file

@ -1,7 +1,7 @@
#!/usr/bin/env node
/**
* This module is started with bin/run.sh. It sets up a Express HTTP and a Socket.IO Server.
* Static file Requests are answered directly from this module, Socket.IO messages are passed
* This module is started with bin/run.sh. It sets up a Express HTTP and a Socket.IO Server.
* Static file Requests are answered directly from this module, Socket.IO messages are passed
* to MessageHandler and minfied requests are passed to minified.
*/
@ -41,7 +41,7 @@ async.waterfall([
callback(er)
})
},
// load everything
function(callback) {
settings = require('./utils/Settings');
@ -54,7 +54,7 @@ async.waterfall([
log4js.setGlobalLogLevel(settings.loglevel);
callback();
},
//initalize the database
function (callback)
{
@ -80,6 +80,6 @@ async.waterfall([
function (callback)
{
hooks.callAll("createServer", {});
callback(null);
callback(null);
}
]);

View file

@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var util = require('util');
var spawn = require('child_process').spawn;
var async = require("async");
@ -35,7 +35,7 @@ if(os.type().indexOf("Windows") > -1)
{
//span an abiword process to perform the conversion
var abiword = spawn(settings.abiword, ["--to=" + task.destFile, task.srcFile]);
//delegate the processing of stdout to another function
abiword.stdout.on('data', function (data)
{
@ -44,7 +44,7 @@ if(os.type().indexOf("Windows") > -1)
});
//append error messages to the buffer
abiword.stderr.on('data', function (data)
abiword.stderr.on('data', function (data)
{
stdoutBuffer += data.toString();
});
@ -64,7 +64,7 @@ if(os.type().indexOf("Windows") > -1)
callback();
});
}
exports.convertFile = function(srcFile, destFile, type, callback)
{
doConvertTask({"srcFile": srcFile, "destFile": destFile, "type": type}, callback);
@ -80,16 +80,16 @@ else
var spawnAbiword = function (){
abiword = spawn(settings.abiword, ["--plugin", "AbiCommand"]);
var stdoutBuffer = "";
var firstPrompt = true;
var firstPrompt = true;
//append error messages to the buffer
abiword.stderr.on('data', function (data)
abiword.stderr.on('data', function (data)
{
stdoutBuffer += data.toString();
});
//abiword died, let's restart abiword and return an error with the callback
abiword.on('exit', function (code)
abiword.on('exit', function (code)
{
spawnAbiword();
stdoutCallback("Abiword died with exit code " + code);
@ -100,16 +100,16 @@ else
{
//add data to buffer
stdoutBuffer+=data.toString();
//we're searching for the prompt, cause this means everything we need is in the buffer
if(stdoutBuffer.search("AbiWord:>") != -1)
{
//filter the feedback message
var err = stdoutBuffer.search("OK") != -1 ? null : stdoutBuffer;
//reset the buffer
stdoutBuffer = "";
//call the callback with the error message
//skip the first prompt
if(stdoutCallback != null && !firstPrompt)
@ -117,7 +117,7 @@ else
stdoutCallback(err);
stdoutCallback = null;
}
firstPrompt = false;
}
});
@ -127,7 +127,7 @@ else
doConvertTask = function(task, callback)
{
abiword.stdin.write("convert " + task.srcFile + " " + task.destFile + " " + task.type + "\n");
//create a callback that calls the task callback and the caller callback
stdoutCallback = function (err)
{
@ -136,12 +136,12 @@ else
task.callback(err);
};
}
//Queue with the converts we have to do
var queue = async.queue(doConvertTask, 1);
exports.convertFile = function(srcFile, destFile, type, callback)
{
{
queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback});
};
}

View file

@ -1,12 +1,12 @@
/**
* Copyright 2011 Adrian Lang
*
*
* 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.

View file

@ -1,12 +1,12 @@
/**
* Copyright 2009 Google Inc.
*
*
* 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.
@ -142,7 +142,7 @@ function getHTMLFromAtext(pad, atext)
assem.append(tags[i]);
assem.append('>');
}
function orderdCloseTags(tags2close)
{
for(var i=0;i<openTags.length;i++)
@ -246,9 +246,9 @@ function getHTMLFromAtext(pad, atext)
tags2close.push(i);
}
}
orderdCloseTags(tags2close);
for (var i = 0; i < propVals.length; i++)
{
if (propVals[i] === ENTER || propVals[i] === STAY)
@ -264,16 +264,16 @@ 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
//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(_encodeWhitespace(Security.escapeHTML(s)));
} // end iteration over spans in line
var tags2close = [];
for (var i = propVals.length - 1; i >= 0; i--)
{
@ -283,7 +283,7 @@ function getHTMLFromAtext(pad, atext)
propVals[i] = false;
}
}
orderdCloseTags(tags2close);
} // end processNextChars
if (urls)
@ -317,7 +317,7 @@ function getHTMLFromAtext(pad, atext)
{
var line = _analyzeLine(textLines[i], attribLines[i], apool);
var lineContent = getLineHTML(line.text, line.aline);
if (line.listLevel)//If we are inside a list
{
// do list stuff
@ -401,8 +401,8 @@ function getHTMLFromAtext(pad, atext)
pieces.push('</li></ul>');
}
lists.length--;
}
var lineContentFromHook = hooks.callAllStr("getLineHTMLForExport",
}
var lineContentFromHook = hooks.callAllStr("getLineHTMLForExport",
{
line: line,
apool: apool,
@ -412,14 +412,14 @@ function getHTMLFromAtext(pad, atext)
if (lineContentFromHook)
{
pieces.push(lineContentFromHook, '');
}
else
}
else
{
pieces.push(lineContent, '<br>');
}
}
}
}
for (var k = lists.length - 1; k >= 0; k--)
{
if(lists[k][1] == "number")
@ -480,14 +480,14 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
{
if(ERR(err, callback)) return;
var head =
(noDocType ? '' : '<!doctype html>\n') +
'<html lang="en">\n' + (noDocType ? '' : '<head>\n' +
var head =
(noDocType ? '' : '<!doctype html>\n') +
'<html lang="en">\n' + (noDocType ? '' : '<head>\n' +
'<title>' + Security.escapeHTML(padId) + '</title>\n' +
'<meta charset="utf-8">\n' +
'<style> * { font-family: arial, sans-serif;\n' +
'font-size: 13px;\n' +
'line-height: 17px; }' +
'<meta charset="utf-8">\n' +
'<style> * { font-family: arial, sans-serif;\n' +
'font-size: 13px;\n' +
'line-height: 17px; }' +
'ul.indent { list-style-type: none; }' +
'ol { list-style-type: decimal; }' +
'ol ol { list-style-type: lower-latin; }' +
@ -497,7 +497,7 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
'ol ol ol ol ol ol{ list-style-type: lower-roman; }' +
'ol ol ol ol ol ol ol { list-style-type: decimal; }' +
'ol ol ol ol ol ol ol ol{ list-style-type: lower-latin; }' +
'</style>\n' + '</head>\n') +
'</style>\n' + '</head>\n') +
'<body>';
var foot = '</body>\n</html>\n';

View file

@ -1,7 +1,7 @@
/**
* This Module manages all /minified/* requests. It controls the
* minification && compression of Javascript and CSS.
*/
* This Module manages all /minified/* requests. It controls the
* minification && compression of Javascript and CSS.
*/
/*
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
@ -149,7 +149,7 @@ function minify(req, res, next)
} else {
res.writeHead(404, {});
res.end();
return;
return;
}
/* Handle static files for plugins/libraries:

View file

@ -1,5 +1,5 @@
/**
* The Settings Modul reads the settings out of settings.json and provides
* The Settings Modul reads the settings out of settings.json and provides
* this information to the other modules
*/
@ -43,7 +43,7 @@ exports.favicon = "favicon.ico";
* The IP ep-lite should listen to
*/
exports.ip = "0.0.0.0";
/**
* The Port ep-lite should listen to
*/

View file

@ -5,11 +5,11 @@ function customError(message, errorName)
{
this.name = errorName || "Error";
this.message = message;
var stackParts = new Error().stack.split("\n");
stackParts.splice(0,2);
stackParts.unshift(this.name + ": " + message);
this.stack = stackParts.join("\n");
}
customError.prototype = Error.prototype;

View file

@ -5,7 +5,7 @@
"keywords" : ["etherpad", "realtime", "collaborative", "editor"],
"author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com> - Primary Technology Ltd",
"contributors" : [
{ "name": "John McLear" },
{ "name": "John McLear" },
{ "name": "Hans Pinckaers" },
{ "name": "Robin Buse" },
{ "name": "Marcel Klehr" }
@ -43,6 +43,6 @@
},
"engines" : { "node" : ">=0.6.0",
"npm" : ">=1.0"
},
},
"version" : "1.1.4"
}

View file

@ -1,130 +1,130 @@
body {
margin: 0;
color: #333;
font: 14px helvetica, sans-serif;
background: #ddd;
background: -webkit-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -moz-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -ms-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
border-top: 8px solid rgba(51,51,51,.8);
}
#wrapper {
margin-top: 160px;
padding: 15px;
background: #fff;
opacity: .9;
box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
max-width: 700px;
margin: auto;
border-radius: 0 0 7px 7px;
}
h1 {
font-size: 29px;
}
h2 {
font-size: 24px;
}
.separator {
margin: 10px 0;
height: 1px;
background: #aaa;
background: -webkit-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
background: -moz-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
background: -ms-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
background: -o-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
}
form {
margin-bottom: 0;
}
#inner {
width: 300px;
margin: 0 auto;
}
input {
font-weight: bold;
font-size: 15px;
}
input[type="button"] {
padding: 4px 6px;
margin: 0;
}
input[type="button"].do-install, input[type="button"].do-uninstall {
float: right;
width: 100px;
}
input[type="button"]#do-search {
display: block;
}
input[type="text"] {
border-radius: 3px;
box-sizing: border-box;
-moz-box-sizing: border-box;
padding: 10px;
*padding: 0; /* IE7 hack */
width: 100%;
outline: none;
border: 1px solid #ddd;
margin: 0 0 5px 0;
max-width: 500px;
}
table {
border: 1px solid #ddd;
border-radius: 3px;
border-spacing: 0;
width: 100%;
margin: 20px 0;
}
table thead tr {
background: #eee;
}
td, th {
padding: 5px;
}
.template {
display: none;
}
.dialog {
display: none;
position: absolute;
left: 50%;
top: 50%;
width: 700px;
height: 500px;
margin-left: -350px;
margin-top: -250px;
border: 3px solid #999;
background: #eee;
}
.dialog .title {
margin: 0;
padding: 2px;
border-bottom: 3px solid #999;
font-size: 24px;
line-height: 24px;
height: 24px;
overflow: hidden;
}
.dialog .title .close {
float: right;
padding: 1px 10px;
}
.dialog .history {
background: #222;
color: #eee;
position: absolute;
top: 41px;
bottom: 10px;
left: 10px;
right: 10px;
padding: 2px;
overflow: auto;
}
.settings {
margin-top:10px;
width:100%;
min-height:600px;
}
#response{
display:inline;
}
body {
margin: 0;
color: #333;
font: 14px helvetica, sans-serif;
background: #ddd;
background: -webkit-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -moz-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -ms-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
border-top: 8px solid rgba(51,51,51,.8);
}
#wrapper {
margin-top: 160px;
padding: 15px;
background: #fff;
opacity: .9;
box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
max-width: 700px;
margin: auto;
border-radius: 0 0 7px 7px;
}
h1 {
font-size: 29px;
}
h2 {
font-size: 24px;
}
.separator {
margin: 10px 0;
height: 1px;
background: #aaa;
background: -webkit-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
background: -moz-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
background: -ms-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
background: -o-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
}
form {
margin-bottom: 0;
}
#inner {
width: 300px;
margin: 0 auto;
}
input {
font-weight: bold;
font-size: 15px;
}
input[type="button"] {
padding: 4px 6px;
margin: 0;
}
input[type="button"].do-install, input[type="button"].do-uninstall {
float: right;
width: 100px;
}
input[type="button"]#do-search {
display: block;
}
input[type="text"] {
border-radius: 3px;
box-sizing: border-box;
-moz-box-sizing: border-box;
padding: 10px;
*padding: 0; /* IE7 hack */
width: 100%;
outline: none;
border: 1px solid #ddd;
margin: 0 0 5px 0;
max-width: 500px;
}
table {
border: 1px solid #ddd;
border-radius: 3px;
border-spacing: 0;
width: 100%;
margin: 20px 0;
}
table thead tr {
background: #eee;
}
td, th {
padding: 5px;
}
.template {
display: none;
}
.dialog {
display: none;
position: absolute;
left: 50%;
top: 50%;
width: 700px;
height: 500px;
margin-left: -350px;
margin-top: -250px;
border: 3px solid #999;
background: #eee;
}
.dialog .title {
margin: 0;
padding: 2px;
border-bottom: 3px solid #999;
font-size: 24px;
line-height: 24px;
height: 24px;
overflow: hidden;
}
.dialog .title .close {
float: right;
padding: 1px 10px;
}
.dialog .history {
background: #222;
color: #eee;
position: absolute;
top: 41px;
bottom: 10px;
left: 10px;
right: 10px;
padding: 2px;
overflow: auto;
}
.settings {
margin-top:10px;
width:100%;
min-height:600px;
}
#response{
display:inline;
}

View file

@ -78,7 +78,7 @@ ul.list-indent8 { list-style-type: none; }
body {
margin: 0;
white-space: nowrap;
}
}
#outerdocbody {
background-color: #fff;

View file

@ -775,7 +775,7 @@ input[type=checkbox] {
border-left: 1px solid #ccc !important;
width: 185px !important;
}
@media screen and (max-width: 600px) {
@media screen and (max-width: 600px) {
.toolbar ul li.separator {
display: none;
}
@ -784,13 +784,13 @@ input[type=checkbox] {
}
}
@media screen and (max-width: 400px){
#editorcontainer {
#editorcontainer {
top: 68px;
}
#editbar {
#editbar {
height: 62px;
}
.toolbar ul.menu_right {
.toolbar ul.menu_right {
float: left;
margin-top:2px;
}

View file

@ -4,23 +4,23 @@ var _ = require('./underscore');
var lineMarkerAttribute = 'lmkr';
// If one of these attributes are set to the first character of a
// If one of these attributes are set to the first character of a
// line it is considered as a line attribute marker i.e. attributes
// set on this marker are applied to the whole line.
// set on this marker are applied to the whole line.
// The list attribute is only maintained for compatibility reasons
var lineAttributes = [lineMarkerAttribute,'list'];
/*
The Attribute manager builds changesets based on a document
The Attribute manager builds changesets based on a document
representation for setting and removing range or line-based attributes.
@param rep the document representation to be used
@param applyChangesetCallback this callback will be called
@param applyChangesetCallback this callback will be called
once a changeset has been built.
A document representation contains
- an array `alines` containing 1 attributes string for each line
A document representation contains
- an array `alines` containing 1 attributes string for each line
- an Attribute pool `apool`
- a SkipList `lines` containing the text lines of the document.
*/
@ -30,7 +30,7 @@ var AttributeManager = function(rep, applyChangesetCallback)
this.rep = rep;
this.applyChangesetCallback = applyChangesetCallback;
this.author = '';
// If the first char in a line has one of the following attributes
// it will be considered as a line marker
};
@ -38,19 +38,19 @@ var AttributeManager = function(rep, applyChangesetCallback)
AttributeManager.lineAttributes = lineAttributes;
AttributeManager.prototype = _(AttributeManager.prototype).extend({
applyChangeset: function(changeset){
if(!this.applyChangesetCallback) return changeset;
var cs = changeset.toString();
if (!Changeset.isIdentity(cs))
{
this.applyChangesetCallback(cs);
}
return changeset;
},
/*
Sets attributes on a range
@param start [row, col] tuple pointing to the start of the range
@ -65,22 +65,22 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
return this.applyChangeset(builder);
},
/*
/*
Returns if the line already has a line marker
@param lineNum: the number of the line
*/
lineHasMarker: function(lineNum){
var that = this;
return _.find(lineAttributes, function(attribute){
return that.getAttributeOnLine(lineNum, attribute) != '';
return that.getAttributeOnLine(lineNum, attribute) != '';
}) !== undefined;
},
/*
Gets a specified attribute on a line
@param lineNum: the number of the line to set the attribute for
@param attributeKey: the name of the attribute to get, e.g. list
@param attributeKey: the name of the attribute to get, e.g. list
*/
getAttributeOnLine: function(lineNum, attributeName){
// get `attributeName` attribute of first char of line
@ -95,26 +95,26 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
}
return '';
},
/*
Sets a specified attribute on a line
@param lineNum: the number of the line to set the attribute for
@param attributeKey: the name of the attribute to set, e.g. list
@param attributeValue: an optional parameter to pass to the attribute (e.g. indention level)
*/
setAttributeOnLine: function(lineNum, attributeName, attributeValue){
var loc = [0,0];
var builder = Changeset.builder(this.rep.lines.totalWidth());
var hasMarker = this.lineHasMarker(lineNum);
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
if(hasMarker){
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 1]), [
[attributeName, attributeValue]
], this.rep.apool);
}else{
}else{
// add a line marker
builder.insert('*', [
['author', this.author],
@ -123,10 +123,10 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
[attributeName, attributeValue]
], this.rep.apool);
}
return this.applyChangeset(builder);
},
/*
Removes a specified attribute on a line
@param lineNum: the number of the affected line
@ -134,19 +134,19 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
*/
removeAttributeOnLine: function(lineNum, attributeName, attributeValue){
var loc = [0,0];
var builder = Changeset.builder(this.rep.lines.totalWidth());
var hasMarker = this.lineHasMarker(lineNum);
if(hasMarker){
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
ChangesetUtils.buildRemoveRange(this.rep, builder, loc, (loc = [lineNum, 1]));
}
return this.applyChangeset(builder);
},
/*
Sets a specified attribute on a line
@param lineNum: the number of the line to set the attribute for
@ -157,7 +157,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
return this.getAttributeOnLine(attributeName) ?
this.removeAttributeOnLine(lineNum, attributeName) :
this.setAttributeOnLine(lineNum, attributeName, attributeValue);
}
});

View file

@ -91,6 +91,6 @@ AttributePool.prototype.fromJsonable = function (obj) {
}
return this;
};
module.exports = AttributePool;

View file

@ -42,7 +42,7 @@ exports.error = function error(msg) {
};
/**
* This method is user for assertions with Messages
* This method is user for assertions with Messages
* if assert fails, the error function called.
* @param b {boolean} assertion condition
* @param msgParts {string} error to be passed if it fails
@ -76,7 +76,7 @@ exports.numToString = function (num) {
* Converts stuff before $ to base 10
* @obsolete not really used anywhere??
* @param cs {string} the string
* @return integer
* @return integer
*/
exports.toBaseTen = function (cs) {
var dollarIndex = cs.indexOf('$');
@ -93,10 +93,10 @@ exports.toBaseTen = function (cs) {
*/
/**
* returns the required length of the text before changeset
* returns the required length of the text before changeset
* can be applied
* @param cs {string} String representation of the Changeset
*/
*/
exports.oldLen = function (cs) {
return exports.unpack(cs).oldLen;
};
@ -104,16 +104,16 @@ exports.oldLen = function (cs) {
/**
* returns the length of the text after changeset is applied
* @param cs {string} String representation of the Changeset
*/
*/
exports.newLen = function (cs) {
return exports.unpack(cs).newLen;
};
/**
* this function creates an iterator which decodes string changeset operations
* @param opsStr {string} String encoding of the change operations to be performed
* @param optStartIndex {int} from where in the string should the iterator start
* @return {Op} type object iterator
* @param opsStr {string} String encoding of the change operations to be performed
* @param optStartIndex {int} from where in the string should the iterator start
* @return {Op} type object iterator
*/
exports.opIterator = function (opsStr, optStartIndex) {
//print(opsStr);
@ -131,7 +131,7 @@ exports.opIterator = function (opsStr, optStartIndex) {
if (result[0] == '?') {
exports.error("Hit error opcode in op stream");
}
return result;
}
var regexResult = nextRegexMatch();
@ -504,7 +504,7 @@ exports.opAssembler = function () {
/**
* A custom made String Iterator
* @param str {string} String to be iterated over
*/
*/
exports.stringIterator = function (str) {
var curIndex = 0;
@ -542,7 +542,7 @@ exports.stringIterator = function (str) {
};
/**
* A custom made StringBuffer
* A custom made StringBuffer
*/
exports.stringAssembler = function () {
var pieces = [];
@ -820,12 +820,12 @@ exports.textLinesMutator = function (lines) {
};
/**
* Function allowing iterating over two Op strings.
* Function allowing iterating over two Op strings.
* @params in1 {string} first Op string
* @params idx1 {int} integer where 1st iterator should start
* @params in2 {string} second Op string
* @params idx2 {int} integer where 2nd iterator should start
* @params func {function} which decides how 1st or 2nd iterator
* @params func {function} which decides how 1st or 2nd iterator
* advances. When opX.opcode = 0, iterator X advances to
* next element
* func has signature f(op1, op2, opOut)
@ -882,7 +882,7 @@ exports.unpack = function (cs) {
};
/**
* Packs Changeset object into a string
* Packs Changeset object into a string
* @params oldLen {int} Old length of the Changeset
* @params newLen {int] New length of the Changeset
* @params opsStr {string} String encoding of the changes to be made
@ -958,8 +958,8 @@ exports.mutateTextLines = function (cs, lines) {
* Composes two attribute strings (see below) into one.
* @param att1 {string} first attribute string
* @param att2 {string} second attribue string
* @param resultIsMutaton {boolean}
* @param pool {AttribPool} attribute pool
* @param resultIsMutaton {boolean}
* @param pool {AttribPool} attribute pool
*/
exports.composeAttributes = function (att1, att2, resultIsMutation, pool) {
// att1 and att2 are strings like "*3*f*1c", asMutation is a boolean.
@ -1019,8 +1019,8 @@ exports.composeAttributes = function (att1, att2, resultIsMutation, pool) {
};
/**
* Function used as parameter for applyZip to apply a Changeset to an
* attribute
* Function used as parameter for applyZip to apply a Changeset to an
* attribute
*/
exports._slicerZipperFunc = function (attOp, csOp, opOut, pool) {
// attOp is the op from the sequence that is being operated on, either an
@ -1337,7 +1337,7 @@ exports.compose = function (cs1, cs2, pool) {
* returns a function that tests if a string of attributes
* (e.g. *3*4) contains a given attribute key,value that
* is already present in the pool.
* @param attribPair array [key,value] of the attribute
* @param attribPair array [key,value] of the attribute
* @param pool {AttribPool} Attribute pool
*/
exports.attributeTester = function (attribPair, pool) {
@ -1369,9 +1369,9 @@ exports.identity = function (N) {
/**
* creates a Changeset which works on oldFullText and removes text
* from spliceStart to spliceStart+numRemoved and inserts newText
* instead. Also gives possibility to add attributes optNewTextAPairs
* creates a Changeset which works on oldFullText and removes text
* from spliceStart to spliceStart+numRemoved and inserts newText
* instead. Also gives possibility to add attributes optNewTextAPairs
* for the new text.
* @param oldFullText {string} old text
* @param spliecStart {int} where splicing starts
@ -1407,7 +1407,7 @@ exports.makeSplice = function (oldFullText, spliceStart, numRemoved, newText, op
* @param cs Changeset
*/
exports.toSplices = function (cs) {
//
//
var unpacked = exports.unpack(cs);
var splices = [];
@ -1438,7 +1438,7 @@ exports.toSplices = function (cs) {
};
/**
*
*
*/
exports.characterRangeFollow = function (cs, startChar, endChar, insertionsAfter) {
var newStartChar = startChar;
@ -1524,7 +1524,7 @@ exports.makeAttribution = function (text) {
* and runs function func on them
* @param cs {Changeset} changeset
* @param func {function} function to be called
*/
*/
exports.eachAttribNumber = function (cs, func) {
var dollarPos = cs.indexOf('$');
if (dollarPos < 0) {
@ -1543,16 +1543,16 @@ exports.eachAttribNumber = function (cs, func) {
* callable on a exports, attribution string, or attribs property of an op,
* though it may easily create adjacent ops that can be merged.
* @param cs {Changeset} changeset to be filtered
* @param filter {function} fnc which returns true if an
* @param filter {function} fnc which returns true if an
* attribute X (int) should be kept in the Changeset
*/
*/
exports.filterAttribNumbers = function (cs, filter) {
return exports.mapAttribNumbers(cs, filter);
};
/**
* does exactly the same as exports.filterAttribNumbers
*/
* does exactly the same as exports.filterAttribNumbers
*/
exports.mapAttribNumbers = function (cs, func) {
var dollarPos = cs.indexOf('$');
if (dollarPos < 0) {
@ -1577,7 +1577,7 @@ exports.mapAttribNumbers = function (cs, func) {
/**
* Create a Changeset going from Identity to a certain state
* @params text {string} text of the final change
* @attribs attribs {string} optional, operations which insert
* @attribs attribs {string} optional, operations which insert
* the text and also puts the right attributes
*/
exports.makeAText = function (text, attribs) {
@ -1588,9 +1588,9 @@ exports.makeAText = function (text, attribs) {
};
/**
* Apply a Changeset to a AText
* Apply a Changeset to a AText
* @param cs {Changeset} Changeset to be applied
* @param atext {AText}
* @param atext {AText}
* @param pool {AttribPool} Attribute Pool to add to
*/
exports.applyToAText = function (cs, atext, pool) {
@ -1602,7 +1602,7 @@ exports.applyToAText = function (cs, atext, pool) {
/**
* Clones a AText structure
* @param atext {AText}
* @param atext {AText}
*/
exports.cloneAText = function (atext) {
return {
@ -1613,7 +1613,7 @@ exports.cloneAText = function (atext) {
/**
* Copies a AText structure from atext1 to atext2
* @param atext {AText}
* @param atext {AText}
*/
exports.copyAText = function (atext1, atext2) {
atext2.text = atext1.text;
@ -1622,7 +1622,7 @@ exports.copyAText = function (atext1, atext2) {
/**
* Append the set of operations from atext to an assembler
* @param atext {AText}
* @param atext {AText}
* @param assem Assembler like smartOpAssembler
*/
exports.appendATextToAssembler = function (atext, assem) {
@ -1660,7 +1660,7 @@ exports.appendATextToAssembler = function (atext, assem) {
/**
* Creates a clone of a Changeset and it's APool
* @param cs {Changeset}
* @param cs {Changeset}
* @param pool {AtributePool}
*/
exports.prepareForWire = function (cs, pool) {
@ -1681,8 +1681,8 @@ exports.isIdentity = function (cs) {
};
/**
* returns all the values of attributes with a certain key
* in an Op attribs string
* returns all the values of attributes with a certain key
* in an Op attribs string
* @param attribs {string} Attribute string of a Op
* @param key {string} string to be seached for
* @param pool {AttribPool} attribute pool
@ -1692,8 +1692,8 @@ exports.opAttributeValue = function (op, key, pool) {
};
/**
* returns all the values of attributes with a certain key
* in an attribs string
* returns all the values of attributes with a certain key
* in an attribs string
* @param attribs {string} Attribute string
* @param key {string} string to be seached for
* @param pool {AttribPool} attribute pool
@ -1711,7 +1711,7 @@ exports.attribsAttributeValue = function (attribs, key, pool) {
};
/**
* Creates a Changeset builder for a string with initial
* Creates a Changeset builder for a string with initial
* length oldLen. Allows to add/remove parts of it
* @param oldLen {int} Old length
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -86,7 +86,7 @@ function Ace2Editor()
});
actionsPendingInit = [];
}
ace2.registry[info.id] = info;
// The following functions (prefixed by 'ace_') are exposed by editor, but
@ -97,7 +97,7 @@ function Ace2Editor()
'applyChangesToBase', 'applyPreparedChangesetToBase',
'setUserChangeNotificationCallback', 'setAuthorInfo',
'setAuthorSelectionRange', 'callWithAce', 'execCommand', 'replaceRange'];
_.each(aceFunctionsPendingInit, function(fnName,i){
var prefix = 'ace_';
var name = prefix + fnName;
@ -105,18 +105,18 @@ function Ace2Editor()
info[prefix + fnName].apply(this, arguments);
});
});
editor.exportText = function()
{
if (!loaded) return "(awaiting init)\n";
return info.ace_exportText();
};
editor.getFrame = function()
{
return info.frame || null;
};
editor.getDebugProperty = function(prop)
{
return info.ace_getDebugProperty(prop);
@ -221,16 +221,16 @@ function Ace2Editor()
// calls to these functions ($$INCLUDE_...) are replaced when this file is processed
// and compressed, putting the compressed code from the named file directly into the
// source here.
// these lines must conform to a specific format because they are passed by the build script:
// these lines must conform to a specific format because they are passed by the build script:
var includedCSS = [];
var $$INCLUDE_CSS = function(filename) {includedCSS.push(filename)};
$$INCLUDE_CSS("../static/css/iframe_editor.css");
$$INCLUDE_CSS("../static/css/pad.css");
$$INCLUDE_CSS("../static/custom/pad.css");
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
includedCSS = includedCSS.concat(additionalCSS);
pushStyleTagsFor(iframeHTML, includedCSS);
if (!Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[KERNEL_SOURCE]) {
@ -304,11 +304,11 @@ window.onload = function () {\n\
$$INCLUDE_CSS("../static/css/iframe_editor.css");
$$INCLUDE_CSS("../static/css/pad.css");
$$INCLUDE_CSS("../static/custom/pad.css");
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
includedCSS = includedCSS.concat(additionalCSS);
pushStyleTagsFor(outerHTML, includedCSS);
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -36,10 +36,10 @@ var isNodeText = Ace2Common.isNodeText,
htmlPrettyEscape = Ace2Common.htmlPrettyEscape,
noop = Ace2Common.noop;
var hooks = require('./pluginfw/hooks');
function Ace2Inner(){
var makeChangesetTracker = require('./changesettracker').makeChangesetTracker;
var colorutils = require('./colorutils').colorutils;
var makeContentCollector = require('./contentcollector').makeContentCollector;
@ -53,9 +53,9 @@ function Ace2Inner(){
var undoModule = require('./undomodule').undoModule;
var makeVirtualLineView = require('./virtual_lines').makeVirtualLineView;
var AttributeManager = require('./AttributeManager');
var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;"
// changed to false
// changed to false
var isSetUp = false;
var THE_TAB = ' '; //4
@ -83,9 +83,9 @@ function Ace2Inner(){
initLineNumbers();
var outsideKeyDown = noop;
var outsideKeyPress = function(){return true;};
var outsideNotifyDirty = noop;
// selFocusAtStart -- determines whether the selection extends "backwards", so that the focus
@ -101,7 +101,7 @@ function Ace2Inner(){
alines: [],
apool: new AttribPool()
};
// lines, alltext, alines, and DOM are set up in setup()
if (undoModule.enabled)
{
@ -113,7 +113,7 @@ function Ace2Inner(){
var doesWrap = true;
var hasLineNumbers = true;
var isStyled = true;
// space around the innermost iframe element
var iframePadLeft = MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT;
var iframePadTop = EDIT_BODY_PADDING_TOP;
@ -122,7 +122,7 @@ function Ace2Inner(){
var console = (DEBUG && window.console);
var documentAttributeManager;
if (!window.console)
{
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
@ -158,7 +158,7 @@ function Ace2Inner(){
var textFace = 'monospace';
var textSize = 12;
function textLineHeight()
{
@ -231,15 +231,15 @@ function Ace2Inner(){
{
bgcolor = fadeColor(bgcolor, info.fade);
}
var authorStyle = dynamicCSS.selectorStyle(getAuthorColorClassSelector(
getAuthorClassName(author)));
var anchorStyle = dynamicCSS.selectorStyle(getAuthorColorClassSelector(
getAuthorClassName(author))+' > a')
// author color
authorStyle.backgroundColor = bgcolor;
// text contrast
if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5)
{
@ -247,7 +247,7 @@ function Ace2Inner(){
}else{
authorStyle.color = null;
}
// anchor text contrast
if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.55)
{
@ -540,8 +540,8 @@ function Ace2Inner(){
{
return rep.lines.atOffset(charOffset).key;
}
function dispose()
{
disposed = true;
@ -896,14 +896,14 @@ function Ace2Inner(){
editorInfo.ace_doReturnKey = doReturnKey;
editorInfo.ace_isBlockElement = isBlockElement;
editorInfo.ace_getLineListType = getLineListType;
editorInfo.ace_callWithAce = function(fn, callStack, normalize)
{
var wrapper = function()
{
return fn(editorInfo);
};
if (normalize !== undefined)
{
var wrapper1 = wrapper;
@ -929,14 +929,14 @@ function Ace2Inner(){
// @param value the value to set to
editorInfo.ace_setProperty = function(key, value)
{
// Convinience function returning a setter for a class on an element
// Convinience function returning a setter for a class on an element
var setClassPresenceNamed = function(element, cls){
return function(value){
setClassPresence(element, cls, !! value)
}
};
// These properties are exposed
var setters = {
wraps: setWraps,
@ -951,7 +951,7 @@ function Ace2Inner(){
},
grayedout: setClassPresenceNamed(outerWin.document.body, "grayedout"),
dmesg: function(){ dmesg = window.dmesg = value; },
userauthor: function(value){
userauthor: function(value){
thisAuthor = String(value);
documentAttributeManager.author = thisAuthor;
},
@ -960,10 +960,10 @@ function Ace2Inner(){
textsize: setTextSize,
rtlistrue: setClassPresenceNamed(root, "rtl")
};
var setter = setters[key.toLowerCase()];
// check if setter is present
// check if setter is present
if(setter !== undefined){
setter(value)
}
@ -1067,7 +1067,7 @@ function Ace2Inner(){
return false;
}
};
isTimeUp.elapsed = function()
{
return now() - startTime;
@ -1448,7 +1448,7 @@ function Ace2Inner(){
var p = PROFILER("getSelection", false);
var selection = getSelection();
p.end();
function topLevel(n)
{
if ((!n) || n == root) return null;
@ -1458,7 +1458,7 @@ function Ace2Inner(){
}
return n;
}
if (selection)
{
var node1 = topLevel(selection.startPoint.node);
@ -1704,7 +1704,7 @@ function Ace2Inner(){
root:root,
point:selection.startPoint,
documentAttributeManager: documentAttributeManager
});
});
selStart = (selStartFromHook==null||selStartFromHook.length==0)?getLineAndCharForPoint(selection.startPoint):selStartFromHook;
}
if (selection && !selEnd)
@ -1717,7 +1717,7 @@ function Ace2Inner(){
point:selection.endPoint,
documentAttributeManager: documentAttributeManager
});
selEnd = (selEndFromHook==null||selEndFromHook.length==0)?getLineAndCharForPoint(selection.endPoint):selEndFromHook;
selEnd = (selEndFromHook==null||selEndFromHook.length==0)?getLineAndCharForPoint(selection.endPoint):selEndFromHook;
}
// selection from content collection can, in various ways, extend past final
@ -1738,7 +1738,7 @@ function Ace2Inner(){
// update rep if we have a new selection
// NOTE: IE loses the selection when you click stuff in e.g. the
// editbar, so removing the selection when it's lost is not a good
// idea.
// idea.
if (selection) repSelectionChange(selStart, selEnd, selection && selection.focusAtStart);
// update browser selection
p.mark("browsel");
@ -1873,19 +1873,19 @@ function Ace2Inner(){
return rep.selStart[0];
}
editorInfo.ace_caretLine = caretLine;
function caretColumn()
{
return rep.selStart[1];
}
editorInfo.ace_caretColumn = caretColumn;
function caretDocChar()
{
return rep.lines.offsetOfIndex(caretLine()) + caretColumn();
}
editorInfo.ace_caretDocChar = caretDocChar;
function handleReturnIndentation()
{
// on return, indent to level of previous line
@ -2314,8 +2314,8 @@ function Ace2Inner(){
documentAttributeManager.setAttributesOnRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
}
editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange;
function setAttributeOnSelection(attributeName, attributeValue)
{
if (!(rep.selStart && rep.selEnd)) return;
@ -2879,7 +2879,7 @@ function Ace2Inner(){
{
if (lineClass !== null) lineElem.className = lineClass;
};
result.prepareForAdd = writeClass;
result.finishUpdate = writeClass;
result.getInnerHTML = function()
@ -3241,7 +3241,7 @@ function Ace2Inner(){
{
return (n.tagName || '').toLowerCase() == "a" && n.href;
}
// only want to catch left-click
if ((!evt.ctrlKey) && (evt.button != 2) && (evt.button != 3))
{
@ -3277,7 +3277,7 @@ function Ace2Inner(){
{
return;
}
var lineNum = rep.selStart[0];
var listType = getLineListType(lineNum);
@ -3287,7 +3287,7 @@ function Ace2Inner(){
listType = /([a-z]+)([12345678])/.exec(listType);
var type = listType[1];
var level = Number(listType[2]);
//detect empty list item; exclude indentation
if(text === '*' && type !== "indent")
{
@ -3401,9 +3401,9 @@ function Ace2Inner(){
var thisLineListType = getLineListType(theLine);
var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1));
var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker);
var thisLineHasMarker = documentAttributeManager.lineHasMarker(theLine);
if (thisLineListType)
{
// this line is a list
@ -3478,7 +3478,7 @@ function Ace2Inner(){
return !!REGEX_WORDCHAR.exec(c);
}
editorInfo.ace_isWordChar = isWordChar;
function isSpaceChar(c)
{
return !!REGEX_SPACE.exec(c);
@ -4011,7 +4011,7 @@ function Ace2Inner(){
maxIndex: tn.nodeValue.length
};
};
var selection = {};
if (origSelectionRange.compareEndPoints("StartToEnd", origSelectionRange) === 0)
{
@ -4875,9 +4875,9 @@ function Ace2Inner(){
}
}
}
var listAttributeName = 'list';
function getLineListType(lineNum)
{
return documentAttributeManager.getAttributeOnLine(lineNum, listAttributeName)
@ -4890,7 +4890,7 @@ function Ace2Inner(){
}else{
documentAttributeManager.setAttributeOnLine(lineNum, listAttributeName, listType);
}
//if the list has been removed, it is necessary to renumber
//starting from the *next* line because the list may have been
//separated. If it returns null, it means that the list was not cut, try
@ -4900,7 +4900,7 @@ function Ace2Inner(){
renumberList(lineNum);
}
}
function renumberList(lineNum){
//1-check we are in a list
var type = getLineListType(lineNum);
@ -4913,7 +4913,7 @@ function Ace2Inner(){
{
return null;
}
//2-find the first line of the list
while(lineNum-1 >= 0 && (type=getLineListType(lineNum-1)))
{
@ -4922,7 +4922,7 @@ function Ace2Inner(){
break;
lineNum--;
}
//3-renumber every list item of the same level from the beginning, level 1
//IMPORTANT: never skip a level because there imbrication may be arbitrary
var builder = Changeset.builder(rep.lines.totalWidth());
@ -4949,7 +4949,7 @@ function Ace2Inner(){
ChangesetUtils.buildKeepRange(rep, builder, loc, (loc = [line, 1]), [
['start', position]
], rep.apool);
position++;
line++;
}
@ -4964,19 +4964,19 @@ function Ace2Inner(){
}
return line;
}
applyNumberList(lineNum, 1);
var cs = builder.toString();
if (!Changeset.isIdentity(cs))
{
performDocumentApplyChangeset(cs);
}
//4-apply the modifications
}
function doInsertList(type)
{
@ -5014,12 +5014,12 @@ function Ace2Inner(){
var t = getLineListType(n);
mods.push([n, allLinesAreList ? 'indent' + level : (t ? type + level : type + '1')]);
}
_.each(mods, function(mod){
setLineListType(mod[0], mod[1]);
});
}
function doInsertUnorderedList(){
doInsertList('bullet');
}
@ -5353,7 +5353,7 @@ function Ace2Inner(){
}
};
})());
var lineNumbersShown;
var sideDivInner;
@ -5369,11 +5369,11 @@ function Ace2Inner(){
var newNumLines = rep.lines.length();
if (newNumLines < 1) newNumLines = 1;
//update height of all current line numbers
var a = sideDivInner.firstChild;
var b = doc.body.firstChild;
var n = 0;
if (currentCallStack && currentCallStack.domClean)
{
@ -5403,8 +5403,8 @@ function Ace2Inner(){
b = b.nextSibling;
n++;
}
}
}
if (newNumLines != lineNumbersShown)
{
var container = sideDivInner;
@ -5414,21 +5414,21 @@ function Ace2Inner(){
{
lineNumbersShown++;
var n = lineNumbersShown;
var div = odoc.createElement("DIV");
var div = odoc.createElement("DIV");
//calculate height for new line number
var h = (b.clientHeight || b.offsetHeight);
if (b.nextSibling)
h = b.nextSibling.offsetTop - b.offsetTop;
if(h) // apply style to div
div.style.height = h +"px";
div.appendChild(odoc.createTextNode(String(n)));
fragment.appendChild(div);
b = b.nextSibling;
}
container.appendChild(fragment);
while (lineNumbersShown > newNumLines)
{
@ -5437,8 +5437,8 @@ function Ace2Inner(){
}
}
}
// Init documentAttributeManager
documentAttributeManager = new AttributeManager(rep, performDocumentApplyChangeset);
editorInfo.ace_performDocumentApplyAttributesToRange = function () {
@ -5484,13 +5484,13 @@ function Ace2Inner(){
bindTheEventHandlers();
});
hooks.callAll('aceInitialized', {
editorInfo: editorInfo,
rep: rep,
documentAttributeManager: documentAttributeManager
});
scheduler.setTimeout(function()
{
parent.readyFunc(); // defined in code that sets up the inner iframe

View file

@ -1,180 +1,180 @@
// Autosize 1.13 - jQuery plugin for textareas
// (c) 2012 Jack Moore - jacklmoore.com
// license: www.opensource.org/licenses/mit-license.php
(function ($) {
var
defaults = {
className: 'autosizejs',
append: "",
callback: false
},
hidden = 'hidden',
borderBox = 'border-box',
lineHeight = 'lineHeight',
copy = '<textarea tabindex="-1" style="position:absolute; top:-9999px; left:-9999px; right:auto; bottom:auto; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
// line-height is omitted because IE7/IE8 doesn't return the correct value.
copyStyle = [
'fontFamily',
'fontSize',
'fontWeight',
'fontStyle',
'letterSpacing',
'textTransform',
'wordSpacing',
'textIndent'
],
oninput = 'oninput',
onpropertychange = 'onpropertychange',
test = $(copy)[0];
// For testing support in old FireFox
test.setAttribute(oninput, "return");
if ($.isFunction(test[oninput]) || onpropertychange in test) {
// test that line-height can be accurately copied to avoid
// incorrect value reporting in old IE and old Opera
$(test).css(lineHeight, '99px');
if ($(test).css(lineHeight) === '99px') {
copyStyle.push(lineHeight);
}
$.fn.autosize = function (options) {
options = $.extend({}, defaults, options || {});
return this.each(function () {
var
ta = this,
$ta = $(ta),
mirror,
minHeight = $ta.height(),
maxHeight = parseInt($ta.css('maxHeight'), 10),
active,
i = copyStyle.length,
resize,
boxOffset = 0,
value = ta.value,
callback = $.isFunction(options.callback);
if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox){
boxOffset = $ta.outerHeight() - $ta.height();
}
if ($ta.data('mirror') || $ta.data('ismirror')) {
// if autosize has already been applied, exit.
// if autosize is being applied to a mirror element, exit.
return;
} else {
mirror = $(copy).data('ismirror', true).addClass(options.className)[0];
resize = $ta.css('resize') === 'none' ? 'none' : 'horizontal';
$ta.data('mirror', $(mirror)).css({
overflow: hidden,
overflowY: hidden,
wordWrap: 'break-word',
resize: resize
});
}
// Opera returns '-1px' when max-height is set to 'none'.
maxHeight = maxHeight && maxHeight > 0 ? maxHeight : 9e4;
// Using mainly bare JS in this function because it is going
// to fire very often while typing, and needs to very efficient.
function adjust() {
var height, overflow, original;
// the active flag keeps IE from tripping all over itself. Otherwise
// actions in the adjust function will cause IE to call adjust again.
if (!active) {
active = true;
mirror.value = ta.value + options.append;
mirror.style.overflowY = ta.style.overflowY;
original = parseInt(ta.style.height,10);
// Update the width in case the original textarea width has changed
mirror.style.width = $ta.css('width');
// Needed for IE to reliably return the correct scrollHeight
mirror.scrollTop = 0;
// Set a very high value for scrollTop to be sure the
// mirror is scrolled all the way to the bottom.
mirror.scrollTop = 9e4;
height = mirror.scrollTop;
overflow = hidden;
if (height > maxHeight) {
height = maxHeight;
overflow = 'scroll';
} else if (height < minHeight) {
height = minHeight;
}
height += boxOffset;
ta.style.overflowY = overflow;
if (original !== height) {
ta.style.height = height + 'px';
if (callback) {
options.callback.call(ta);
}
}
// This small timeout gives IE a chance to draw it's scrollbar
// before adjust can be run again (prevents an infinite loop).
setTimeout(function () {
active = false;
}, 1);
}
}
// mirror is a duplicate textarea located off-screen that
// is automatically updated to contain the same text as the
// original textarea. mirror always has a height of 0.
// This gives a cross-browser supported way getting the actual
// height of the text, through the scrollTop property.
while (i--) {
mirror.style[copyStyle[i]] = $ta.css(copyStyle[i]);
}
$('body').append(mirror);
if (onpropertychange in ta) {
if (oninput in ta) {
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
// so binding to onkeyup to catch most of those occassions. There is no way that I
// know of to detect something like 'cut' in IE9.
ta[oninput] = ta.onkeyup = adjust;
} else {
// IE7 / IE8
ta[onpropertychange] = adjust;
}
} else {
// Modern Browsers
ta[oninput] = adjust;
// The textarea overflow is now hidden. But Chrome doesn't reflow the text after the scrollbars are removed.
// This is a hack to get Chrome to reflow it's text.
ta.value = '';
ta.value = value;
}
$(window).resize(adjust);
// Allow for manual triggering if needed.
$ta.bind('autosize', adjust);
// Call adjust in case the textarea already contains text.
adjust();
});
};
} else {
// Makes no changes for older browsers (FireFox3- and Safari4-)
$.fn.autosize = function (callback) {
return this;
};
}
// Autosize 1.13 - jQuery plugin for textareas
// (c) 2012 Jack Moore - jacklmoore.com
// license: www.opensource.org/licenses/mit-license.php
(function ($) {
var
defaults = {
className: 'autosizejs',
append: "",
callback: false
},
hidden = 'hidden',
borderBox = 'border-box',
lineHeight = 'lineHeight',
copy = '<textarea tabindex="-1" style="position:absolute; top:-9999px; left:-9999px; right:auto; bottom:auto; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
// line-height is omitted because IE7/IE8 doesn't return the correct value.
copyStyle = [
'fontFamily',
'fontSize',
'fontWeight',
'fontStyle',
'letterSpacing',
'textTransform',
'wordSpacing',
'textIndent'
],
oninput = 'oninput',
onpropertychange = 'onpropertychange',
test = $(copy)[0];
// For testing support in old FireFox
test.setAttribute(oninput, "return");
if ($.isFunction(test[oninput]) || onpropertychange in test) {
// test that line-height can be accurately copied to avoid
// incorrect value reporting in old IE and old Opera
$(test).css(lineHeight, '99px');
if ($(test).css(lineHeight) === '99px') {
copyStyle.push(lineHeight);
}
$.fn.autosize = function (options) {
options = $.extend({}, defaults, options || {});
return this.each(function () {
var
ta = this,
$ta = $(ta),
mirror,
minHeight = $ta.height(),
maxHeight = parseInt($ta.css('maxHeight'), 10),
active,
i = copyStyle.length,
resize,
boxOffset = 0,
value = ta.value,
callback = $.isFunction(options.callback);
if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox){
boxOffset = $ta.outerHeight() - $ta.height();
}
if ($ta.data('mirror') || $ta.data('ismirror')) {
// if autosize has already been applied, exit.
// if autosize is being applied to a mirror element, exit.
return;
} else {
mirror = $(copy).data('ismirror', true).addClass(options.className)[0];
resize = $ta.css('resize') === 'none' ? 'none' : 'horizontal';
$ta.data('mirror', $(mirror)).css({
overflow: hidden,
overflowY: hidden,
wordWrap: 'break-word',
resize: resize
});
}
// Opera returns '-1px' when max-height is set to 'none'.
maxHeight = maxHeight && maxHeight > 0 ? maxHeight : 9e4;
// Using mainly bare JS in this function because it is going
// to fire very often while typing, and needs to very efficient.
function adjust() {
var height, overflow, original;
// the active flag keeps IE from tripping all over itself. Otherwise
// actions in the adjust function will cause IE to call adjust again.
if (!active) {
active = true;
mirror.value = ta.value + options.append;
mirror.style.overflowY = ta.style.overflowY;
original = parseInt(ta.style.height,10);
// Update the width in case the original textarea width has changed
mirror.style.width = $ta.css('width');
// Needed for IE to reliably return the correct scrollHeight
mirror.scrollTop = 0;
// Set a very high value for scrollTop to be sure the
// mirror is scrolled all the way to the bottom.
mirror.scrollTop = 9e4;
height = mirror.scrollTop;
overflow = hidden;
if (height > maxHeight) {
height = maxHeight;
overflow = 'scroll';
} else if (height < minHeight) {
height = minHeight;
}
height += boxOffset;
ta.style.overflowY = overflow;
if (original !== height) {
ta.style.height = height + 'px';
if (callback) {
options.callback.call(ta);
}
}
// This small timeout gives IE a chance to draw it's scrollbar
// before adjust can be run again (prevents an infinite loop).
setTimeout(function () {
active = false;
}, 1);
}
}
// mirror is a duplicate textarea located off-screen that
// is automatically updated to contain the same text as the
// original textarea. mirror always has a height of 0.
// This gives a cross-browser supported way getting the actual
// height of the text, through the scrollTop property.
while (i--) {
mirror.style[copyStyle[i]] = $ta.css(copyStyle[i]);
}
$('body').append(mirror);
if (onpropertychange in ta) {
if (oninput in ta) {
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
// so binding to onkeyup to catch most of those occassions. There is no way that I
// know of to detect something like 'cut' in IE9.
ta[oninput] = ta.onkeyup = adjust;
} else {
// IE7 / IE8
ta[onpropertychange] = adjust;
}
} else {
// Modern Browsers
ta[oninput] = adjust;
// The textarea overflow is now hidden. But Chrome doesn't reflow the text after the scrollbars are removed.
// This is a hack to get Chrome to reflow it's text.
ta.value = '';
ta.value = value;
}
$(window).resize(adjust);
// Allow for manual triggering if needed.
$ta.bind('autosize', adjust);
// Call adjust in case the textarea already contains text.
adjust();
});
};
} else {
// Makes no changes for older browsers (FireFox3- and Safari4-)
$.fn.autosize = function (callback) {
return this;
};
}
}(jQuery));

View file

@ -7,18 +7,18 @@
if (typeof global.JSON == "undefined" || !global.JSON) {
global.JSON = {};
}
global.JSON.minify = function(json) {
var tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r/g,
in_string = false,
in_multiline_comment = false,
in_singleline_comment = false,
tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc
;
tokenizer.lastIndex = 0;
while (tmp = tokenizer.exec(json)) {
lc = RegExp.leftContext;
rc = RegExp.rightContext;
@ -30,7 +30,7 @@
new_str[ns++] = tmp2;
}
from = tokenizer.lastIndex;
if (tmp[0] == "\"" && !in_multiline_comment && !in_singleline_comment) {
tmp2 = lc.match(/(\\)*$/);
if (!in_string || !tmp2 || (tmp2[0].length % 2) == 0) { // start of string with ", or unescaped " character found to end string

View file

@ -1,5 +1,5 @@
$(document).ready(function () {
var socket,
loc = document.location,
port = loc.port == "" ? (loc.protocol == "https:" ? 443 : 80) : loc.port,
@ -81,7 +81,7 @@ $(document).ready(function () {
message = "<span class='status'>" + data.message.toString() + "</span>";
}
if (data.error) {
message = "<span class='error'>" + data.error.toString() + "<span>";
message = "<span class='error'>" + data.error.toString() + "<span>";
}
$("#progress.dialog .message").html(message);
$("#progress.dialog .history").append("<div>" + message + "</div>");

View file

@ -18,11 +18,11 @@ $(document).ready(function () {
{
$('.settings').append(settings.results);
$('.settings').focus();
$('.settings').autosize();
$('.settings').autosize();
}
else{
alert("YOUR JSON IS BAD AND YOU SHOULD FEEL BAD");
}
}
});
/* When the admin clicks save Settings check the JSON then send the JSON back to the server */

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -274,12 +274,12 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
padContents.currentTime += timeDelta;
debugLog('Time Delta: ', timeDelta)
updateTimer();
var authors = _.map(padContents.getActiveAuthors(), function(name)
{
return authorData[name];
});
BroadcastSlider.setAuthors(authors);
}
@ -292,9 +292,9 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
str = '0' + str;
return str;
}
var date = new Date(padContents.currentTime);
var dateFormat = function()
{
@ -306,18 +306,18 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
var seconds = zpad(date.getSeconds(), 2);
return ([month, '/', day, '/', year, ' ', hours, ':', minutes, ':', seconds].join(""));
}
$('#timer').html(dateFormat());
var revisionDate = ["Saved", ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"][date.getMonth()], date.getDate() + ",", date.getFullYear()].join(" ")
$('#revision_date').html(revisionDate)
}
updateTimer();
function goToRevision(newRevision)
@ -380,7 +380,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
changesetLoader.queueUp(start, 1, update);
}
var authors = _.map(padContents.getActiveAuthors(), function(name){
return authorData[name];
});
@ -549,7 +549,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
goToRevision.apply(goToRevision, arguments);
}
}
BroadcastSlider.onSlider(goToRevisionIfEnabled);
var dynamicCSS = makeCSSManager('dynamicsyntax');

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -56,7 +56,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
slidercallbacks[i](newval);
}
}
var updateSliderElements = function()
{
for (var i = 0; i < savedRevisions.length; i++)
@ -65,7 +65,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
savedRevisions[i].css('left', (position * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0)) - 1);
}
$("#ui-slider-handle").css('left', sliderPos * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0));
}
}
var addSavedRevision = function(position, info)
{
@ -162,7 +162,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
var height = $('#timeslider-top').height();
$('#editorcontainerbox').css({marginTop: height});
}, 600);
function setAuthors(authors)
{
var authorsList = $("#authorsList");
@ -176,7 +176,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
if (author.name)
{
if (numNamed !== 0) authorsList.append(', ');
$('<span />')
.text(author.name || "unnamed")
.css('background-color', authorColor)
@ -199,11 +199,11 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
} else {
authorsList.append(anonymousAuthorString);
}
if(colorsAnonymous.length > 0){
authorsList.append(' (');
_.each(colorsAnonymous, function(color, i){
if( i > 0 ) authorsList.append(' ');
if( i > 0 ) authorsList.append(' ');
$('<span>&nbsp;</span>')
.css('background-color', color)
.addClass('author author-anonymous')
@ -211,13 +211,13 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
});
authorsList.append(')');
}
}
if (authors.length == 0)
{
authorsList.append("No Authors");
}
fixPadHeight();
}
@ -275,7 +275,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
{
disableSelection($("#playpause_button")[0]);
disableSelection($("#timeslider")[0]);
$(document).keyup(function(e)
{
var code = -1;
@ -320,7 +320,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
else if (code == 32) playpause();
});
$(window).resize(function()
{
updateSliderElements();
@ -470,16 +470,16 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
$("#revision").css('right', "20px");
$("#revision").css('top', "20px");
}
$("#timeslider").show();
setSliderLength(clientVars.collab_client_vars.rev);
setSliderPosition(clientVars.collab_client_vars.rev);
_.each(clientVars.savedRevisions, function(revision)
{
addSavedRevision(revision.revNum, revision);
})
}
});
})();

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -30,8 +30,8 @@ var chat = (function()
var isStuck = false;
var chatMentions = 0;
var self = {
show: function ()
{
show: function ()
{
$("#chaticon").hide();
$("#chatbox").show();
self.scrollDown();
@ -55,7 +55,7 @@ var chat = (function()
isStuck = false;
}
},
hide: function ()
hide: function ()
{
$("#chatcounter").text("0");
$("#chaticon").show();
@ -69,7 +69,7 @@ var chat = (function()
self.lastMessage = $('#chattext > p').eq(-1);
}
}
},
},
send: function()
{
var text = $("#chatinput").val();
@ -77,10 +77,10 @@ var chat = (function()
$("#chatinput").val("");
},
addMessage: function(msg, increment)
{
{
//correct the time
msg.time += this._pad.clientTimeOffset;
//create the time string
var minutes = "" + new Date(msg.time).getMinutes();
var hours = "" + new Date(msg.time).getHours();
@ -89,7 +89,7 @@ var chat = (function()
if(hours.length == 1)
hours = "0" + hours ;
var timeStr = hours + ":" + minutes;
//create the authorclass
var authorClass = "author-" + msg.userId.replace(/[^a-y0-9]/g, function(c)
{
@ -109,20 +109,20 @@ var chat = (function()
}
/* End of new action */
var authorName = msg.userName == null ? "unnamed" : padutils.escapeHtml(msg.userName);
var authorName = msg.userName == null ? "unnamed" : padutils.escapeHtml(msg.userName);
var html = "<p class='" + authorClass + "'><b>" + authorName + ":</b><span class='time " + authorClass + "'>" + timeStr + "</span> " + text + "</p>";
$("#chattext").append(html);
//should we increment the counter??
if(increment)
{
var count = Number($("#chatcounter").text());
count++;
// is the users focus already in the chatbox?
var alreadyFocused = $("#chatinput").is(":focus");
$("#chatcounter").text(count);
// chat throb stuff -- Just make it throw for twice as long
if(wasMentioned && !alreadyFocused)
@ -156,7 +156,7 @@ var chat = (function()
self.send();
}
});
var that = this;
$.each(clientVars.chatHistory, function(i, o){
that.addMessage(o, false);

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -366,7 +366,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
msg.userInfo.colorId = initialUserInfo.globalUserColor;
}
if (userSet[id])
{
userSet[id] = userInfo;
@ -433,7 +433,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
{
colorId = clientVars.colorPalette[colorId];
}
var cssColor = colorId;
if (inactive)
{

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -241,14 +241,14 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
{
state.listNesting = (state.listNesting || 0) + 1;
}
if(listType === 'none' || !listType ){
delete state.lineAttributes['list'];
delete state.lineAttributes['list'];
}
else{
state.lineAttributes['list'] = listType;
}
_recalcAttribString(state);
return oldListType;
}
@ -315,7 +315,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
return [key, value];
})
);
lines.appendText('*', Changeset.makeAttribsString('+', attributes , apool));
}
cc.startNewLine = function(state)
@ -385,7 +385,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
text:txt,
styl: null,
cls: null
});
});
var txt = (typeof(txtFromHook)=='object'&&txtFromHook.length==0)?dom.nodeValue(node):txtFromHook[0];
var rest = '';
@ -454,7 +454,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
{
var tname = (dom.nodeTagName(node) || "").toLowerCase();
if (tname == "br")
{
{
this.breakLine = true;
var tvalue = dom.nodeAttr(node, 'value');
var induceLineBreak = hooks.callAll('collectContentLineBreak', {
@ -464,11 +464,11 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
tvalue:tvalue,
styl: null,
cls: null
});
});
var startNewLine= (typeof(induceLineBreak)=='object'&&induceLineBreak.length==0)?true:induceLineBreak[0];
if(startNewLine){
cc.startNewLine(state);
}
}
}
else if (tname == "script" || tname == "style")
{

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -26,7 +26,7 @@ function makeCSSManager(emptyStylesheetTitle)
function getSheetByTitle(title)
{
var allSheets = document.styleSheets;
for (var i = 0; i < allSheets.length; i++)
{
var s = allSheets[i];
@ -37,7 +37,7 @@ function makeCSSManager(emptyStylesheetTitle)
}
return null;
}
var browserSheet = getSheetByTitle(emptyStylesheetTitle);
function browserRules()

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -82,7 +82,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
}
var html = [];
var preHtml = '',
var preHtml = '',
postHtml = '';
var curHTML = null;
@ -118,10 +118,10 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
preHtml = '<ol '+start+' class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
postHtml = '</li></ol>';
}
}
}
processedMarker = true;
}
_.map(hooks.callAll("aceDomLineProcessLineAttributes", {
domline: domline,
cls: cls
@ -131,11 +131,11 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
postHtml += modifier.postHtml;
processedMarker |= modifier.processedMarker;
});
if( processedMarker ){
result.lineMarker += txt.length;
return; // don't append any text
}
}
}
@ -229,7 +229,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
result.node.innerHTML = curHTML;
}
if (lineClass !== null) result.node.className = lineClass;
hooks.callAll("acePostWriteDomLineHTML", {
node: result.node
});

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,6 +1,6 @@
// Farbtastic 2.0 alpha
(function ($) {
var __debug = false;
var __factor = 0.5;
@ -16,7 +16,7 @@ $.farbtastic = function (container, options) {
$._farbtastic = function (container, options) {
var fb = this;
/////////////////////////////////////////////////////
/**
@ -134,7 +134,7 @@ $._farbtastic = function (container, options) {
fb.ctxOverlay = fb.cnvOverlay[0].getContext('2d');
fb.ctxMask.translate(fb.mid, fb.mid);
fb.ctxOverlay.translate(fb.mid, fb.mid);
// Draw widget base layers.
fb.drawCircle();
fb.drawMask();
@ -208,7 +208,7 @@ $._farbtastic = function (container, options) {
m.restore();
__debug && $('body').append('<div>drawCircle '+ (+(new Date()) - tm) +'ms');
};
/**
* Draw the saturation/luminance mask.
*/
@ -232,9 +232,9 @@ $._farbtastic = function (container, options) {
outputPixel(x, y, c, a);
}
}
}
}
// Method #1: direct pixel access (new Canvas).
if (fb.ctxMask.getImageData) {
// Create half-resolution buffer.
@ -295,7 +295,7 @@ $._farbtastic = function (container, options) {
}
cache.push([c, a]);
});
}
}
__debug && $('body').append('<div>drawMask '+ (+(new Date()) - tm) +'ms');
}
@ -343,7 +343,7 @@ $._farbtastic = function (container, options) {
// Draw markers
fb.drawMarkers();
// Linked elements or callback
if (typeof fb.callback == 'object') {
// Set background/foreground color
@ -363,15 +363,15 @@ $._farbtastic = function (container, options) {
fb.callback.call(fb, fb.color);
}
}
/**
* Helper for returning coordinates relative to the center.
*/
fb.widgetCoords = function (event) {
return {
x: event.pageX - fb.offset.left - fb.mid,
x: event.pageX - fb.offset.left - fb.mid,
y: event.pageY - fb.offset.top - fb.mid
};
};
}
/**
@ -434,7 +434,7 @@ $._farbtastic = function (container, options) {
fb.packDX = function (c, a) {
return '#' + fb.dec2hex(a) + fb.dec2hex(c) + fb.dec2hex(c) + fb.dec2hex(c);
};
fb.pack = function (rgb) {
var r = Math.round(rgb[0] * 255);
var g = Math.round(rgb[1] * 255);

View file

@ -3885,7 +3885,7 @@ var Sizzle = function( selector, context, results, seed ) {
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
return [];
}
if ( !selector || typeof selector !== "string" ) {
return results;
}
@ -3895,7 +3895,7 @@ var Sizzle = function( selector, context, results, seed ) {
contextXML = Sizzle.isXML( context ),
parts = [],
soFar = selector;
// Reset the position of the chunker regexp (start from head)
do {
chunker.exec( "" );
@ -3903,9 +3903,9 @@ var Sizzle = function( selector, context, results, seed ) {
if ( m ) {
soFar = m[3];
parts.push( m[1] );
if ( m[2] ) {
extra = m[3];
break;
@ -3929,7 +3929,7 @@ var Sizzle = function( selector, context, results, seed ) {
if ( Expr.relative[ selector ] ) {
selector += parts.shift();
}
set = posProcess( selector, set, seed );
}
}
@ -4057,7 +4057,7 @@ Sizzle.find = function( expr, context, isXML ) {
for ( i = 0, len = Expr.order.length; i < len; i++ ) {
type = Expr.order[i];
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
left = match[1];
match.splice( 1, 1 );
@ -4429,7 +4429,7 @@ var Expr = Sizzle.selectors = {
ATTR: function( match, curLoop, inplace, result, not, isXML ) {
var name = match[1] = match[1].replace( rBackslash, "" );
if ( !isXML && Expr.attrMap[name] ) {
match[1] = Expr.attrMap[name];
}
@ -4463,7 +4463,7 @@ var Expr = Sizzle.selectors = {
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
return true;
}
return match;
},
@ -4473,7 +4473,7 @@ var Expr = Sizzle.selectors = {
return match;
}
},
filters: {
enabled: function( elem ) {
return elem.disabled === false && elem.type !== "hidden";
@ -4486,14 +4486,14 @@ var Expr = Sizzle.selectors = {
checked: function( elem ) {
return elem.checked === true;
},
selected: function( elem ) {
// Accessing this property makes selected-by-default
// options in Safari work properly
if ( elem.parentNode ) {
elem.parentNode.selectedIndex;
}
return elem.selected === true;
},
@ -4515,7 +4515,7 @@ var Expr = Sizzle.selectors = {
text: function( elem ) {
var attr = elem.getAttribute( "type" ), type = elem.type;
// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
// use getAttribute instead to test this case
return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
},
@ -4634,21 +4634,21 @@ var Expr = Sizzle.selectors = {
case "only":
case "first":
while ( (node = node.previousSibling) ) {
if ( node.nodeType === 1 ) {
return false;
if ( node.nodeType === 1 ) {
return false;
}
}
if ( type === "first" ) {
return true;
if ( type === "first" ) {
return true;
}
node = elem;
case "last":
while ( (node = node.nextSibling) ) {
if ( node.nodeType === 1 ) {
return false;
if ( node.nodeType === 1 ) {
return false;
}
}
@ -4661,22 +4661,22 @@ var Expr = Sizzle.selectors = {
if ( first === 1 && last === 0 ) {
return true;
}
doneName = match[0];
parent = elem.parentNode;
if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
count = 0;
for ( node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType === 1 ) {
node.nodeIndex = ++count;
}
}
}
parent[ expando ] = doneName;
}
diff = elem.nodeIndex - last;
if ( first === 0 ) {
@ -4695,7 +4695,7 @@ var Expr = Sizzle.selectors = {
TAG: function( elem, match ) {
return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
},
CLASS: function( elem, match ) {
return (" " + (elem.className || elem.getAttribute("class")) + " ")
.indexOf( match ) > -1;
@ -4765,7 +4765,7 @@ var makeArray = function( array, results ) {
results.push.apply( results, array );
return results;
}
return array;
};
@ -4997,7 +4997,7 @@ if ( document.querySelectorAll ) {
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
return;
}
Sizzle = function( query, context, extra, seed ) {
context = context || document;
@ -5006,24 +5006,24 @@ if ( document.querySelectorAll ) {
if ( !seed && !Sizzle.isXML(context) ) {
// See if we find a selector to speed up
var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
// Speed-up: Sizzle("TAG")
if ( match[1] ) {
return makeArray( context.getElementsByTagName( query ), extra );
// Speed-up: Sizzle(".CLASS")
} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
return makeArray( context.getElementsByClassName( match[2] ), extra );
}
}
if ( context.nodeType === 9 ) {
// Speed-up: Sizzle("body")
// The body element only exists once, optimize finding it
if ( query === "body" && context.body ) {
return makeArray( [ context.body ], extra );
// Speed-up: Sizzle("#ID")
} else if ( match && match[3] ) {
var elem = context.getElementById( match[3] );
@ -5036,12 +5036,12 @@ if ( document.querySelectorAll ) {
if ( elem.id === match[3] ) {
return makeArray( [ elem ], extra );
}
} else {
return makeArray( [], extra );
}
}
try {
return makeArray( context.querySelectorAll(query), extra );
} catch(qsaError) {}
@ -5079,7 +5079,7 @@ if ( document.querySelectorAll ) {
}
}
}
return oldSizzle(query, context, extra, seed);
};
@ -5106,7 +5106,7 @@ if ( document.querySelectorAll ) {
// This should fail with an exception
// Gecko does not error, returns false instead
matches.call( document.documentElement, "[test!='']:sizzle" );
} catch( pseudoError ) {
pseudoWorks = true;
}
@ -5116,7 +5116,7 @@ if ( document.querySelectorAll ) {
expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
if ( !Sizzle.isXML( node ) ) {
try {
try {
if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
var ret = matches.call( node, expr );
@ -5153,7 +5153,7 @@ if ( document.querySelectorAll ) {
if ( div.getElementsByClassName("e").length === 1 ) {
return;
}
Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function( match, context, isXML ) {
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
@ -5204,7 +5204,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
if ( elem ) {
var match = false;
elem = elem[dir];
while ( elem ) {
@ -5257,7 +5257,7 @@ if ( document.documentElement.contains ) {
Sizzle.isXML = function( elem ) {
// documentElement is verified for cases where it doesn't yet exist
// (such as loading iframes in IE - #4833)
// (such as loading iframes in IE - #4833)
var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
return documentElement ? documentElement.nodeName !== "HTML" : false;
@ -5374,11 +5374,11 @@ jQuery.fn.extend({
},
is: function( selector ) {
return !!selector && (
return !!selector && (
typeof selector === "string" ?
// If this is a positional selector, check membership in the returned set
// so $("p:first").is("p:last") won't return true for a doc with two "p".
POS.test( selector ) ?
POS.test( selector ) ?
jQuery( selector, this.context ).index( this[0] ) >= 0 :
jQuery.filter( selector, this ).length > 0 :
this.filter( selector ).length > 0 );
@ -5386,7 +5386,7 @@ jQuery.fn.extend({
closest: function( selectors, context ) {
var ret = [], i, l, cur = this[0];
// Array (deprecated as of jQuery 1.7)
if ( jQuery.isArray( selectors ) ) {
var level = 1;

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -74,10 +74,10 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
{
var classes = '';
var isLineAttribMarker = false;
Changeset.eachAttribNumber(attribs, function(n)
{
var key = apool.getAttribKey(n);
var key = apool.getAttribKey(n);
if (key)
{
var value = apool.getAttribValue(n);
@ -109,11 +109,11 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
key: key,
value: value
}, " ", " ", "");
}
}
}
}
});
if(isLineAttribMarker) classes += ' ' + lineAttributeMarker;
return classes.substring(1);
}
@ -146,12 +146,12 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
return function(txt, cls)
{
var disableAuthColorForThisLine = hooks.callAll("disableAuthorColorsForThisLine", {
linestylefilter: linestylefilter,
text: txt,
"class": cls
}, " ", " ", "");
}, " ", " ", "");
var disableAuthors = (disableAuthColorForThisLine==null||disableAuthColorForThisLine.length==0)?false:disableAuthColorForThisLine[0];
while (txt.length > 0)
{

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -60,10 +60,10 @@ function createCookie(name, value, days, path)
var expires = "; expires=" + date.toGMTString();
}
else var expires = "";
if(!path)
path = "/";
document.cookie = name + "=" + value + expires + "; path=" + path;
}
@ -117,7 +117,7 @@ function getParams()
if(showControls)
{
if(showControls == "false")
{
{
$('#editbar').hide();
$('#editorcontainer').css({"top":"0px"});
}
@ -220,7 +220,7 @@ function handshake()
token = "t." + randomString();
createCookie("token", token, 60);
}
var sessionID = readCookie("sessionID");
var password = readCookie("password");
@ -233,14 +233,14 @@ function handshake()
"token": token,
"protocolVersion": 2
};
//this is a reconnect, lets tell the server our revisionnumber
if(isReconnect == true)
{
msg.client_rev=pad.collabClient.getCurrentRevisionNumber();
msg.reconnect=true;
}
socket.json.send(msg);
};
@ -249,7 +249,7 @@ function handshake()
socket.once('connect', function () {
sendClientReady(false);
});
socket.on('reconnect', function () {
//reconnect is before the timeout, lets stop the timeout
if(disconnectTimeout)
@ -260,7 +260,7 @@ function handshake()
pad.collabClient.setChannelState("CONNECTED");
sendClientReady(true);
});
socket.on('disconnect', function (reason) {
if(reason == "booted"){
pad.collabClient.setChannelState("DISCONNECTED");
@ -269,9 +269,9 @@ function handshake()
{
pad.collabClient.setChannelState("DISCONNECTED", "reconnect_timeout");
}
pad.collabClient.setChannelState("RECONNECTING");
disconnectTimeout = setTimeout(disconnectEvent, 10000);
}
});
@ -301,7 +301,7 @@ function handshake()
"<button type='button' onclick=\"" + padutils.escapeHtml('require('+JSON.stringify(module.id)+").savePassword()") + "\">ok</button>");
}
}
//if we haven't recieved the clientVars yet, then this message should it be
else if (!receivedClientVars)
{
@ -314,7 +314,7 @@ function handshake()
clientVars = obj.data;
clientVars.userAgent = "Anonymous";
clientVars.collab_client_vars.clientAgent = "Anonymous";
//initalize the pad
pad._afterHandshake();
initalized = true;
@ -336,7 +336,7 @@ function handshake()
{
pad.changeViewOption('noColors', true);
}
if (settings.rtlIsTrue == true)
{
pad.changeViewOption('rtl', true);
@ -457,7 +457,7 @@ var pad = {
_afterHandshake: function()
{
pad.clientTimeOffset = new Date().getTime() - clientVars.serverTimestamp;
//initialize the chat
chat.init(this);
pad.initTime = +(new Date());
@ -481,7 +481,7 @@ var pad = {
// order of inits is important here:
padcookie.init(clientVars.cookiePrefsToSet, this);
$("#widthprefcheck").click(pad.toggleWidthPref);
// $("#sidebarcheck").click(pad.togglewSidebar);
@ -749,20 +749,20 @@ var pad = {
pad.diagnosticInfo.disconnectedMessage = message;
pad.diagnosticInfo.padId = pad.getPadId();
pad.diagnosticInfo.socket = {};
//we filter non objects from the socket object and put them in the diagnosticInfo
//we filter non objects from the socket object and put them in the diagnosticInfo
//this ensures we have no cyclic data - this allows us to stringify the data
for(var i in socket.socket)
{
var value = socket.socket[i];
var type = typeof value;
if(type == "string" || type == "number")
{
pad.diagnosticInfo.socket[i] = value;
}
}
pad.asyncSendDiagnosticInfo();
if (typeof window.ajlog == "string")
{

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -43,7 +43,7 @@ var padconnectionstatus = (function()
status = {
what: 'connected'
};
padmodals.showModal('connected');
padmodals.hideOverlay(500);
},
@ -52,7 +52,7 @@ var padconnectionstatus = (function()
status = {
what: 'reconnecting'
};
padmodals.showModal('reconnecting');
padmodals.showOverlay(500);
},
@ -60,18 +60,18 @@ var padconnectionstatus = (function()
{
if(status.what == "disconnected")
return;
status = {
what: 'disconnected',
why: msg
};
var k = String(msg).toLowerCase(); // known reason why
if (!(k == 'userdup' || k == 'deleted' || k == 'looping' || k == 'slowcommit' || k == 'initsocketfail' || k == 'unauth'))
{
k = 'disconnected';
}
padmodals.showModal(k);
padmodals.showOverlay(500);
},

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -117,7 +117,7 @@ var padeditbar = (function()
$("#editbar").addClass('disabledtoolbar').removeClass("enabledtoolbar");
},
toolbarClick: function(cmd)
{
{
if (self.isEnabled())
{
if(cmd == "showusers")
@ -189,7 +189,7 @@ var padeditbar = (function()
toggleDropDown: function(moduleName, cb)
{
var modules = ["settings", "connectivity", "importexport", "embed", "users"];
// hide all modules and remove highlighting of all buttons
if(moduleName == "none")
{
@ -199,9 +199,9 @@ var padeditbar = (function()
//skip the userlist
if(modules[i] == "users")
continue;
var module = $("#" + modules[i]);
if(module.css('display') != "none")
{
$("#" + modules[i] + "link").removeClass("selected");
@ -211,14 +211,14 @@ var padeditbar = (function()
}
if(!returned && cb) return cb();
}
else
else
{
// hide all modules that are not selected and remove highlighting
// respectively add highlighting to the corresponding button
for(var i=0;i<modules.length;i++)
{
var module = $("#" + modules[i]);
if(module.css('display') != "none")
{
$("#" + modules[i] + "link").removeClass("selected");

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -71,7 +71,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()
{
@ -128,13 +128,13 @@ var padimpexp = (function()
function importErrorMessage(status)
{
var msg="";
if(status === "convertFailed"){
msg = "We were not able to import this file. Please use a different document format or copy paste manually";
} else if(status === "uploadFailed"){
msg = "The upload failed, please try again";
}
function showError(fade)
{
$('#importmessagefail').html('<strong style="color: red">Import failed:</strong> ' + (msg || 'Please copy paste'))[(fade ? "fadeIn" : "show")]();
@ -218,7 +218,7 @@ var padimpexp = (function()
$("#exporthtmla").attr("href", pad_root_path + "/export/html");
$("#exportplaina").attr("href", pad_root_path + "/export/txt");
$("#exportdokuwikia").attr("href", pad_root_path + "/export/dokuwiki");
//hide stuff thats not avaible if abiword is disabled
if(clientVars.abiwordAvailable == "no")
{
@ -231,24 +231,24 @@ var padimpexp = (function()
else if(clientVars.abiwordAvailable == "withoutPDF")
{
$("#exportpdfa").remove();
$("#exportworda").attr("href", pad_root_path + "/export/doc");
$("#exportopena").attr("href", pad_root_path + "/export/odt");
$("#importexport").css({"height":"142px"});
$("#importexportline").css({"height":"142px"});
$("#importform").attr('action', pad_root_url + "/import");
$("#importform").attr('action', pad_root_url + "/import");
}
else
{
$("#exportworda").attr("href", pad_root_path + "/export/doc");
$("#exportpdfa").attr("href", pad_root_path + "/export/pdf");
$("#exportopena").attr("href", pad_root_path + "/export/odt");
$("#importform").attr('action', pad_root_path + "/import");
$("#importform").attr('action', pad_root_path + "/import");
}
$("#impexp-close").click(function()
{
paddocbar.setShownPanel(null);
@ -265,7 +265,7 @@ var padimpexp = (function()
{
importFailed(status);
}
importDone();
},
disable: function()

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -19,7 +19,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var padutils = require('./pad_utils').padutils;
var padeditbar = require('./pad_editbar').padeditbar;

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -516,7 +516,7 @@ var paduserlist = (function()
{
info.colorId = clientVars.colorPalette[info.colorId];
}
myUserInfo = $.extend(
{}, info);
@ -725,9 +725,9 @@ var paduserlist = (function()
{
$("#myswatchbox").addClass('myswatchboxhoverable').removeClass('myswatchboxunhoverable');
}
$("#myswatch").css({'background-color': myUserInfo.colorId});
if ($.browser.msie && parseInt($.browser.version) <= 8) {
$("#usericon a").css({'box-shadow': 'inset 0 0 30px ' + myUserInfo.colorId,'background-color': myUserInfo.colorId});
}
@ -749,7 +749,7 @@ function getColorPickerSwatchIndex(jnode)
function closeColorPicker(accept)
{
if (accept)
{
{
var newColor = $("#mycolorpickerpreview").css("background-color");
var parts = newColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
// parts now should be ["rgb(0, 70, 255", "0", "70", "255"]

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -518,9 +518,9 @@ function setupGlobalExceptionHandler() {
var errObj = {errorInfo: JSON.stringify({errorId: errorId, msg: msg, url: url, linenumber: linenumber, userAgent: navigator.userAgent})};
var loc = document.location;
var url = loc.protocol + "//" + loc.hostname + ":" + loc.port + "/" + loc.pathname.substr(1, loc.pathname.indexOf("/p/")) + "jserror";
$.post(url, errObj);
return false;
};
window.onerror = globalExceptionHandler;

View file

@ -43,7 +43,7 @@ exports.uninstall = function(plugin_name, cb) {
});
},
function () {
hooks.aCallAll("restartServer", {}, function () {});
hooks.aCallAll("restartServer", {}, function () {});
},
cb
);
@ -61,7 +61,7 @@ exports.install = function(plugin_name, cb) {
});
},
function () {
hooks.aCallAll("restartServer", {}, function () {});
hooks.aCallAll("restartServer", {}, function () {});
},
cb
);

View file

@ -105,11 +105,11 @@ exports.getPackages = function (cb) {
delete packages[name].dependencies;
delete packages[name].parent;
}
if (deps[name].dependencies !== undefined) flatten(deps[name].dependencies);
});
}
var tmp = {};
tmp[data.name] = data;
flatten(tmp);

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
@ -155,7 +155,7 @@ function SkipList()
var widthLoc = point.widthSkips[0] + point.nodes[0].downSkipWidths[0];
var newWidth = _entryWidth(entry);
p.mark("loop1");
// The new node will have at least level 1
// With a proability of 0.01^(n-1) the nodes level will be >= n
while (newNode.levels == 0 || Math.random() < 0.01)

View file

@ -60,7 +60,7 @@ function init() {
var url = loc.protocol + "//" + loc.hostname + ":" + port + "/";
//find out in which subfolder we are
var resource = exports.baseURL.substring(1) + 'socket.io';
//build up the socket io connection
socket = io.connect(url, {resource: resource});
@ -128,13 +128,13 @@ function sendSocketMsg(type, data)
}
var fireWhenAllScriptsAreLoaded = [];
var BroadcastSlider, changesetLoader;
function handleClientVars(message)
{
//save the client Vars
clientVars = message.data;
//load all script that doesn't work without the clientVars
BroadcastSlider = require('./broadcast_slider').loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded);
require('./broadcast_revisions').loadBroadcastRevisionsJS();

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -1,5 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/

View file

@ -44,7 +44,7 @@
.test_group table {
width: 100%;
}
#apikeyDIV {
width: 100%
}
@ -64,7 +64,7 @@
callFunction(name, results_node, params);
});
var template = $('#template')
$('.define').each(function() {
var functionName = parseName($(this).text());
@ -95,7 +95,7 @@
{
// parse out the parameters by looking for parens
var parens = str.substring(str.indexOf("("));
// return empty array if there are no paremeters
if(parens.length < 3)
{
@ -109,10 +109,10 @@
return parens.split(',');
}
function callFunction(memberName, results_node, params)
function callFunction(memberName, results_node, params)
{
$('#result').text('Calling ' + memberName + "()...");
params["apikey"]=$("#apikey").val();
$.ajax({
type: "GET",
@ -138,7 +138,7 @@
</tr>
</table>
<div class="results"></div>
</div>
<div class="define">createGroup()</div>
<div class="define">deleteGroup(groupID)</div>

View file

@ -1,20 +1,20 @@
<html>
<head>
<title>Etherpad Lite Admin Dashboard</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link rel="stylesheet" href="../static/css/admin.css">
<script src="../static/js/jquery.js"></script>
<script src="../socket.io/socket.io.js"></script>
</head>
<body>
<div id="wrapper">
<h1>Etherpad Lite Admin Dashboard</h1>
<div>
<a href="../admin/plugins">Install and Uninstall plugins</a>
</div>
<div>
<a href="../admin/settings">Modify Server and Plugin Settings</a>
</div>
</div>
</body>
</html>
<html>
<head>
<title>Etherpad Lite Admin Dashboard</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link rel="stylesheet" href="../static/css/admin.css">
<script src="../static/js/jquery.js"></script>
<script src="../socket.io/socket.io.js"></script>
</head>
<body>
<div id="wrapper">
<h1>Etherpad Lite Admin Dashboard</h1>
<div>
<a href="../admin/plugins">Install and Uninstall plugins</a>
</div>
<div>
<a href="../admin/settings">Modify Server and Plugin Settings</a>
</div>
</div>
</body>
</html>

View file

@ -1,90 +1,90 @@
<html>
<head>
<title>Plugin manager</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link rel="stylesheet" href="../static/css/admin.css">
<script src="../static/js/jquery.js"></script>
<script src="../socket.io/socket.io.js"></script>
<script src="../static/js/admin/plugins.js"></script>
</head>
<body>
<div id="wrapper">
<% if (errors.length) { %>
<div class="errors">
<% errors.forEach(function (item) { %>
<div class="error"><%= item.toString() %></div>
<% }) %>
</div>
<% } %>
<h1>Etherpad Lite</h1>
<a href="plugins/info">Technical information on installed plugins</a>
<div class="separator"></div>
<h2>Installed plugins</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<td></td>
</tr>
</thead>
<tbody class="template">
<tr id="installed-plugin-template">
<td class="name"></td>
<td class="description"></td>
<td class="actions">
<input type="button" value="Uninstall" class="do-uninstall">
</td>
</tr>
</tbody>
<tbody id="installed-plugins">
</tbody>
</table>
<div class="paged listing search-results">
<div class="separator"></div>
<h2>Search for plugins to install</h2>
<form>
<input type="text" name="search" placeholder="Search term" id="search-query">
<input type="button" value="Search" id="do-search">
</form>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<td></td>
</tr>
</thead>
<tbody class="template">
<tr>
<td class="name"></td>
<td class="description"></td>
<td class="actions">
<input type="button" value="Install" class="do-install">
</td>
</tr>
</tbody>
<tbody class="results">
</tbody>
</table>
<input type="button" value="<<" class="do-prev-page">
<span class="offset"></span>..<span class="limit"></span> of <span class="total"></span>.
<input type="button" value=">>" class="do-next-page">
</div>
<div id="progress" class="dialog">
<h1 class="title">
Please wait: <span class="message"></span>
<input type="button" class="close" value="Close">
</h1>
<div class="history"></div>
</div>
</div>
</body>
</html>
<html>
<head>
<title>Plugin manager</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link rel="stylesheet" href="../static/css/admin.css">
<script src="../static/js/jquery.js"></script>
<script src="../socket.io/socket.io.js"></script>
<script src="../static/js/admin/plugins.js"></script>
</head>
<body>
<div id="wrapper">
<% if (errors.length) { %>
<div class="errors">
<% errors.forEach(function (item) { %>
<div class="error"><%= item.toString() %></div>
<% }) %>
</div>
<% } %>
<h1>Etherpad Lite</h1>
<a href="plugins/info">Technical information on installed plugins</a>
<div class="separator"></div>
<h2>Installed plugins</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<td></td>
</tr>
</thead>
<tbody class="template">
<tr id="installed-plugin-template">
<td class="name"></td>
<td class="description"></td>
<td class="actions">
<input type="button" value="Uninstall" class="do-uninstall">
</td>
</tr>
</tbody>
<tbody id="installed-plugins">
</tbody>
</table>
<div class="paged listing search-results">
<div class="separator"></div>
<h2>Search for plugins to install</h2>
<form>
<input type="text" name="search" placeholder="Search term" id="search-query">
<input type="button" value="Search" id="do-search">
</form>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<td></td>
</tr>
</thead>
<tbody class="template">
<tr>
<td class="name"></td>
<td class="description"></td>
<td class="actions">
<input type="button" value="Install" class="do-install">
</td>
</tr>
</tbody>
<tbody class="results">
</tbody>
</table>
<input type="button" value="<<" class="do-prev-page">
<span class="offset"></span>..<span class="limit"></span> of <span class="total"></span>.
<input type="button" value=">>" class="do-next-page">
</div>
<div id="progress" class="dialog">
<h1 class="title">
Please wait: <span class="message"></span>
<input type="button" class="close" value="Close">
</h1>
<div class="history"></div>
</div>
</div>
</body>
</html>

View file

@ -1,34 +1,34 @@
<html>
<head>
<title>Settings manager</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link rel="stylesheet" href="../static/css/admin.css">
<script src="../static/js/jquery.js"></script>
<script src="../socket.io/socket.io.js"></script>
<script src="../static/js/admin/minify.json.js"></script>
<script src="../static/js/admin/settings.js"></script>
<script src="../static/js/admin/jquery.autosize.js"></script>
</head>
<body>
<div id="wrapper">
<% if (errors.length) { %>
<div class="errors">
<% errors.forEach(function (item) { %>
<div class="error"><%= item.toString() %></div>
<% }) %>
</div>
<% } %>
<h1>Etherpad Lite Settings</h1>
<a href='https://github.com/Pita/etherpad-lite/wiki/Example-Production-Settings.JSON'>Example production settings template</a>
<a href='https://github.com/Pita/etherpad-lite/wiki/Example-Development-Settings.JSON'>Example development settings template</a>
<textarea class="settings"></textarea>
<input type="button" class="settingsButton" id="saveSettings" value="Save Settings">
<input type="button" class="settingsButton" id="restartEtherpad" value="Restart Etherpad">
<div id="response"></div>
</div>
</body>
</html>
<html>
<head>
<title>Settings manager</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link rel="stylesheet" href="../static/css/admin.css">
<script src="../static/js/jquery.js"></script>
<script src="../socket.io/socket.io.js"></script>
<script src="../static/js/admin/minify.json.js"></script>
<script src="../static/js/admin/settings.js"></script>
<script src="../static/js/admin/jquery.autosize.js"></script>
</head>
<body>
<div id="wrapper">
<% if (errors.length) { %>
<div class="errors">
<% errors.forEach(function (item) { %>
<div class="error"><%= item.toString() %></div>
<% }) %>
</div>
<% } %>
<h1>Etherpad Lite Settings</h1>
<a href='https://github.com/Pita/etherpad-lite/wiki/Example-Production-Settings.JSON'>Example production settings template</a>
<a href='https://github.com/Pita/etherpad-lite/wiki/Example-Development-Settings.JSON'>Example development settings template</a>
<textarea class="settings"></textarea>
<input type="button" class="settingsButton" id="saveSettings" value="Save Settings">
<input type="button" class="settingsButton" id="restartEtherpad" value="Restart Etherpad">
<div id="response"></div>
</div>
</body>
</html>

View file

@ -29,7 +29,7 @@
*/
</script>
<meta charset="utf-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link rel="shortcut icon" href="<%=settings.favicon%>">
@ -111,7 +111,7 @@
input[type="text"] {
border-radius: 3px;
box-sizing: border-box;
-moz-box-sizing: border-box;
-moz-box-sizing: border-box;
padding: 0 45px 0 10px;
*padding: 0; /* IE7 hack */
width: 100%;
@ -137,53 +137,53 @@
margin-top: 0;
}
#inner {
width: 95%;
width: 95%;
}
#label {
text-align: center;
}
}
</style>
<link href="static/custom/index.css" rel="stylesheet">
<link href="static/custom/index.css" rel="stylesheet">
<div id="wrapper">
<div id="inner">
<div id="button" onclick="go2Random()" class="translate">New Pad</div>
<div id="label" class="translate">or create/open a Pad with the name</div>
<form action="#" onsubmit="go2Name();return false;">
<input type="text" id="padname" autofocus x-webkit-speech>
<div id="label" class="translate">or create/open a Pad with the name</div>
<form action="#" onsubmit="go2Name();return false;">
<input type="text" id="padname" autofocus x-webkit-speech>
<button type="submit">OK</button>
</form>
</div>
</div>
<script src="static/custom/index.js"></script>
<script>
function go2Name()
<script>
function go2Name()
{
var padname = document.getElementById("padname").value;
padname.length > 0 ? window.location = "p/" + padname : alert("Please enter a name")
}
function go2Random()
function go2Random()
{
window.location = "p/" + randomPadName();
}
function randomPadName()
function randomPadName()
{
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var string_length = 10;
var randomstring = '';
for (var i = 0; i < string_length; i++)
for (var i = 0; i < string_length; i++)
{
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum, rnum + 1);
}
return randomstring;
}
// start the custom js
if (typeof customStart == "function") customStart();
</script>

Some files were not shown because too many files have changed in this diff Show more