Merge branch 'master' of git://github.com/Pita/etherpad-lite

Conflicts:
	static/index.html
	static/pad.html
This commit is contained in:
Eric Martindale 2011-12-08 18:46:59 +00:00
commit a1b66baa63
59 changed files with 791 additions and 1225 deletions

2
.gitignore vendored
View file

@ -7,3 +7,5 @@ bin/node.exe
etherpad-lite-win.zip etherpad-lite-win.zip
var/dirty.db var/dirty.db
bin/convertSettings.json bin/convertSettings.json
*~
*.patch

View file

@ -67,12 +67,11 @@ Here is the **[FAQ](https://github.com/Pita/etherpad-lite/wiki/FAQ)**
<li>Move into the node folder <code>cd node-v0.6*</code> and build node with <code>./configure && make && make install</code></li> <li>Move into the node folder <code>cd node-v0.6*</code> and build node with <code>./configure && make && make install</code></li>
</ol> </ol>
</li> </li>
<li>Install npm <code>curl http://npmjs.org/install.sh | sh</code></li>
</ol> </ol>
**As any user (we recommend creating a separate user called etherpad-lite):** **As any user (we recommend creating a separate user called etherpad-lite):**
<ol start="4"> <ol start="3">
<li>Move to a folder where you want to install Etherpad Lite. Clone the git repository <code>git clone 'git://github.com/Pita/etherpad-lite.git'</code><br>&nbsp;</li> <li>Move to a folder where you want to install Etherpad Lite. Clone the git repository <code>git clone 'git://github.com/Pita/etherpad-lite.git'</code><br>&nbsp;</li>
<li>Install the dependencies with <code>bin/installDeps.sh</code><br>&nbsp;</li> <li>Install the dependencies with <code>bin/installDeps.sh</code><br>&nbsp;</li>
<li>Start it with <code>bin/run.sh</code><br>&nbsp;</li> <li>Start it with <code>bin/run.sh</code><br>&nbsp;</li>
@ -115,8 +114,8 @@ You also help the project, if you only host a Etherpad Lite instance and share y
# Modules created for this project # Modules created for this project
* [ueberDB](https://github.com/Pita/ueberDB) "transforms every database into a object key value store" - manages all database access * [ueberDB](https://github.com/Pita/ueberDB) "transforms every database into a object key value store" - manages all database access
* [doc.md](https://github.com/Pita/doc.md) "A simple JSDoc documentation tool that creates markdown for node.js modules exports" - is used to generate the docs
* [channels](https://github.com/Pita/channels) "Event channels in node.js" - ensures that ueberDB operations are atomic and in series for each key * [channels](https://github.com/Pita/channels) "Event channels in node.js" - ensures that ueberDB operations are atomic and in series for each key
* [async-stacktrace](https://github.com/Pita/async-stacktrace) "Improves node.js stacktraces and makes it easier to handle errors"
# License # License
[Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html) [Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html)

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
NODE_VERSION="0.6.1" NODE_VERSION="0.6.5"
#Move to the folder where ep-lite is installed #Move to the folder where ep-lite is installed
cd `dirname $0` cd `dirname $0`

133
bin/checkPad.js Normal file
View file

@ -0,0 +1,133 @@
/*
This is a debug tool. It checks all revisions for data corruption
*/
if(process.argv.length != 3)
{
console.error("Use: node checkPad.js $PADID");
process.exit(1);
}
//get the padID
var padId = process.argv[2];
//initalize the database
var log4js = require("log4js");
log4js.setGlobalLogLevel("INFO");
var async = require("async");
var db = require('../node/db/DB');
var Changeset = require('../node/utils/Changeset');
var padManager;
async.series([
//intallize the database
function (callback)
{
db.init(callback);
},
//get the pad
function (callback)
{
padManager = require('../node/db/PadManager');
padManager.doesPadExists(padId, function(err, exists)
{
if(!exists)
{
console.error("Pad does not exist");
process.exit(1);
}
padManager.getPad(padId, function(err, _pad)
{
pad = _pad;
callback(err);
});
});
},
function (callback)
{
//create an array with key kevisions
//key revisions always save the full pad atext
var head = pad.getHeadRevisionNumber();
var keyRevisions = [];
for(var i=0;i<head;i+=100)
{
keyRevisions.push(i);
}
//run trough all key revisions
async.forEachSeries(keyRevisions, function(keyRev, callback)
{
//create an array of revisions we need till the next keyRevision or the End
var revisionsNeeded = [];
for(var i=keyRev;i<=keyRev+100 && i<=head; i++)
{
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)
{
db.db.get("pad:"+padId+":revs:" + revNum, function(err, revision)
{
revisions[revNum] = revision;
callback(err);
});
}, function(err)
{
if(err)
{
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)
{
console.error("No atext in key revision " + keyRev);
callback();
return;
}
var apool = pad.pool;
var atext = revisions[keyRev].meta.atext;
for(var i=keyRev+1;i<=keyRev+100 && i<=head; i++)
{
try
{
//console.log("check revision " + i);
var cs = revisions[i].changeset;
atext = Changeset.applyToAText(cs, atext, apool);
}
catch(e)
{
console.error("Bad changeset at revision " + i + " - " + e.message);
callback();
return;
}
}
callback();
});
}, callback);
}
], function (err)
{
if(err) throw err;
else
{
console.log("finished");
process.exit(0);
}
});

View file

@ -1,24 +0,0 @@
#!/bin/sh
#Move to the folder where ep-lite is installed
cd `dirname $0`
#Was this script started in the bin folder? if yes move out
if [ -d "../bin" ]; then
cd "../"
fi
hash node > /dev/null 2>&1 || {
echo "You need to install node!" >&2
exit 1
}
hash doc.md > /dev/null 2>&1 || {
echo "You need to install doc.md! npm install -g doc.md" >&2
exit 1
}
echo "empty doc folder..."
rm -rf doc/jsdoc/*
doc.md node doc/jsdoc

View file

@ -28,8 +28,8 @@ hash npm > /dev/null 2>&1 || {
#check npm version #check npm version
NPM_VERSION=$(npm --version) NPM_VERSION=$(npm --version)
if [ ! $(echo $NPM_VERSION | cut -d "." -f 1-2) = "1.0" ]; then 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.0.x" >&2 echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.x" >&2
exit 1 exit 1
fi fi

View file

@ -1,2 +0,0 @@
# About this folder
This is the documentation generated with doc.md. This documentation might be not up to date, you can generate the latest jsdocs with bin/generateJsDoc.sh

View file

@ -1,53 +0,0 @@
# db/AuthorMana
`require("./db/AuthorManager");`
The AuthorManager controlls all information about the Pad authors
## Functions
- - -
### getAuthor (author, callback)
Internal function that creates the database entry for an author
* **author** *(String)* The id of the author
* **callback** *(Function)* callback(err, authorObj)
- - -
### getAuthor4Token (token, callback)
Returns the Author Id for a token. If the token is unkown,
it creates a author for the token
* **token** *(String)* The token
* **callback** *(Function)* callback (err, author)
The callback function that is called when the result is here
- - -
### getAuthorColorId (author, callback)
Returns the color Id of the author
* **author** *(String)* The id of the author
* **callback** *(Function)* callback(err, colorId)
- - -
### getAuthorName (author, callback)
Returns the name of the author
* **author** *(String)* The id of the author
* **callback** *(Function)* callback(err, name)
- - -
### setAuthorColorId (author, colorId, callback)
Sets the color Id of the author
* **author** *(String)* The id of the author
* **colorId** *No description*
* **callback** *(Function)* (optional)
- - -
### setAuthorName (author, name, callback)
Sets the name of the author
* **author** *(String)* The id of the author
* **name** *No description*
* **callback** *(Function)* (optional)

View file

@ -1,20 +0,0 @@
# db
`require("./db/DB");`
The DB Module provides a database initalized with the settings
provided by the settings module
## Functions
- - -
### init (callback)
Initalizes the database with the settings provided by the settings module
* **callback** *(Function)* *No description*
##Variables
- - -
### db
The UeberDB Object that provides the database functions

View file

@ -1,13 +0,0 @@
# db/
`require("./db/Pad");`
The pad object, defined with joose
## Functions
- - -
### cleanText (txt)
Copied from the Etherpad source code. It converts Windows line breaks to Unix line breaks and convert Tabs to spaces
* **txt** *No description*

View file

@ -1,14 +0,0 @@
# db/PadMana
`require("./db/PadManager");`
The Pad Manager is a Factory for pad Objects
## Functions
- - -
### getPad (id, callback)
A Array with all known Pads
* **id** A String with the id of the pad
* **callback** *(Function)* *No description*

View file

@ -1,21 +0,0 @@
# db/ReadOnlyMana
`require("./db/ReadOnlyManager");`
The ReadOnlyManager manages the database and rendering releated to read only pads
## Functions
- - -
### getPadId (readOnlyId, callback)
returns a the padId for a read only id
* **readOnlyId** *(String)* read only id
* **callback** *No description*
- - -
### getReadOnlyId (padId, callback)
returns a read only id for a pad
* **padId** *(String)* the id of the pad
* **callback** *No description*

View file

@ -1,7 +0,0 @@
# easysync_tests
`require("./easysync_tests");`
I found this tests in the old Etherpad and used it to test if the Changeset library can be run on node.js.
It has no use for ep-lite, but I thought I keep it cause it may help someone to understand the Changeset library
https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2_tests.js

View file

@ -1,16 +0,0 @@
# handler/Expor
`require("./handler/ExportHandler");`
Handles the export requests
## Functions
- - -
### doExport (req, res, padId, type)
do a requested export
* **req** *No description*
* **res** *No description*
* **padId** *No description*
* **type** *No description*

View file

@ -1,15 +0,0 @@
# handler/Impor
`require("./handler/ImportHandler");`
Handles the import requests
## Functions
- - -
### doImport (req, res, padId)
do a requested import
* **req** *No description*
* **res** *No description*
* **padId** *No description*

View file

@ -1,38 +0,0 @@
# handler/PadMessag
`require("./handler/PadMessageHandler");`
The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions
## Functions
- - -
### handleConnect (client)
Handles the connection of a new user
* **client** the new client
- - -
### handleDisconnect (client)
Handles the disconnection of a user
* **client** the client that leaves
- - -
### handleMessage (client, message)
Handles a message from a user
* **client** the client that send this message
* **message** the message from the client
- - -
### setSocketIO (socket_io)
A associative array that translates a session to a pad
* **socket_io** The Socket
- - -
### updatePadClients (pad, callback)
* **pad** *No description*
* **callback** *No description*

View file

@ -1,23 +0,0 @@
# handler/Socket
`require("./handler/SocketIORouter");`
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
## Functions
- - -
### addComponent (moduleName, module)
Saves all components
key is the component name
value is the component module
* **moduleName** *No description*
* **module** *No description*
- - -
### setSocketIO (_socket)
sets the socket.io and adds event functions for routing
* **_socket** *No description*

View file

@ -1,32 +0,0 @@
# handler/TimesliderMessag
`require("./handler/TimesliderMessageHandler");`
The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions
## Functions
- - -
### handleConnect (client)
Handles the connection of a new user
* **client** the new client
- - -
### handleDisconnect (client)
Handles the disconnection of a user
* **client** the client that leaves
- - -
### handleMessage (client, message)
Handles a message from a user
* **client** the client that send this message
* **message** the message from the client
- - -
### setSocketIO (socket_io)
Saves the Socket class we need to send and recieve data from the client
* **socket_io** The Socket

View file

@ -1,13 +0,0 @@
# server
`require("./server");`
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.
##Variables
- - -
### maxAge

View file

@ -1,15 +0,0 @@
# utils/A
`require("./utils/Abiword");`
Controls the communication with the Abiword application
## Functions
- - -
### convertFile (srcFile, destFile, type, callback)
* **srcFile** *No description*
* **destFile** *No description*
* **type** *No description*
* **callback** *No description*

View file

@ -1,15 +0,0 @@
# utils/AttributePoolF
`require("./utils/AttributePoolFactory");`
This code represents the Attribute Pool Object of the original Etherpad.
90% of the code is still like in the original Etherpad
Look at https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js
You can find a explanation what a attribute pool is here:
https://github.com/Pita/etherpad-lite/blob/master/doc/easysync/easysync-notes.txt
## Functions
- - -
### createAttributePool ()

View file

@ -1,363 +0,0 @@
# utils/Cha
`require("./utils/Changeset");`
## Functions
- - -
### _slicerZipperFunc (attOp, csOp, opOut, pool)
* **attOp** *No description*
* **csOp** *No description*
* **opOut** *No description*
* **pool** *No description*
- - -
### appendATextToAssembler (atext, assem)
* **atext** *No description*
* **assem** *No description*
- - -
### applyToAText (cs, atext, pool)
* **cs** *No description*
* **atext** *No description*
* **pool** *No description*
- - -
### applyToAttribution (cs, astr, pool)
* **cs** *No description*
* **astr** *No description*
* **pool** *No description*
- - -
### applyToText (cs, str)
* **cs** *No description*
* **str** *No description*
- - -
### applyZip (in1, idx1, in2, idx2, func)
* **in1** *No description*
* **idx1** *No description*
* **in2** *No description*
* **idx2** *No description*
* **func** *No description*
- - -
### attribsAttributeValue (attribs, key, pool)
* **attribs** *No description*
* **key** *No description*
* **pool** *No description*
- - -
### attributeTester (attribPair, pool)
* **attribPair** *No description*
* **pool** *No description*
- - -
### builder (oldLen)
* **oldLen** *No description*
- - -
### characterRangeFollow (cs, startChar, endChar, insertionsAfter)
* **cs** *No description*
* **startChar** *No description*
* **endChar** *No description*
* **insertionsAfter** *No description*
- - -
### checkRep (cs)
* **cs** *No description*
- - -
### clearOp (op)
* **op** *No description*
- - -
### cloneAText (atext)
* **atext** *No description*
- - -
### cloneOp (op)
* **op** *No description*
- - -
### compose (cs1, cs2, pool)
* **cs1** *No description*
* **cs2** *No description*
* **pool** *No description*
- - -
### composeAttributes (att1, att2, resultIsMutation, pool)
* **att1** *No description*
* **att2** *No description*
* **resultIsMutation** *No description*
* **pool** *No description*
- - -
### copyAText (atext1, atext2)
* **atext1** *No description*
* **atext2** *No description*
- - -
### copyOp (op1, op2)
* **op1** *No description*
* **op2** *No description*
- - -
### eachAttribNumber (cs, func)
* **cs** *No description*
* **func** *No description*
- - -
### filterAttribNumbers (cs, filter)
* **cs** *No description*
* **filter** *No description*
- - -
### follow (cs1, cs2, reverseInsertOrder, pool)
* **cs1** *No description*
* **cs2** *No description*
* **reverseInsertOrder** *No description*
* **pool** *No description*
- - -
### followAttributes (att1, att2, pool)
* **att1** *No description*
* **att2** *No description*
* **pool** *No description*
- - -
### identity (N)
* **N** *No description*
- - -
### inverse (cs, lines, alines, pool)
* **cs** *No description*
* **lines** *No description*
* **alines** *No description*
* **pool** *No description*
- - -
### isIdentity (cs)
* **cs** *No description*
- - -
### joinAttributionLines (theAlines)
* **theAlines** *No description*
- - -
### makeAText (text, attribs)
* **text** *No description*
* **attribs** *No description*
- - -
### makeAttribsString (opcode, attribs, pool)
* **opcode** *No description*
* **attribs** *No description*
* **pool** *No description*
- - -
### makeAttribution (text)
* **text** *No description*
- - -
### makeSplice (oldFullText, spliceStart, numRemoved, newText, optNewTextAPairs, pool)
* **oldFullText** *No description*
* **spliceStart** *No description*
* **numRemoved** *No description*
* **newText** *No description*
* **optNewTextAPairs** *No description*
* **pool** *No description*
- - -
### mapAttribNumbers (cs, func)
* **cs** *No description*
* **func** *No description*
- - -
### mergingOpAssembler ()
- - -
### moveOpsToNewPool (cs, oldPool, newPool)
* **cs** *No description*
* **oldPool** *No description*
* **newPool** *No description*
- - -
### mutateAttributionLines (cs, lines, pool)
* **cs** *No description*
* **lines** *No description*
* **pool** *No description*
- - -
### mutateTextLines (cs, lines)
* **cs** *No description*
* **lines** *No description*
- - -
### newLen (cs)
* **cs** *No description*
- - -
### newOp (optOpcode)
* **optOpcode** *No description*
- - -
### numToString (num)
* **num** *No description*
- - -
### oldLen (cs)
* **cs** *No description*
- - -
### oneInsertedLineAtATimeOpIterator (opsStr, optStartIndex, charBank)
* **opsStr** *No description*
* **optStartIndex** *No description*
* **charBank** *No description*
- - -
### opAssembler ()
- - -
### opAttributeValue (op, key, pool)
* **op** *No description*
* **key** *No description*
* **pool** *No description*
- - -
### opIterator (opsStr, optStartIndex)
* **opsStr** *No description*
* **optStartIndex** *No description*
- - -
### opString (op)
* **op** *No description*
- - -
### pack (oldLen, newLen, opsStr, bank)
* **oldLen** *No description*
* **newLen** *No description*
* **opsStr** *No description*
* **bank** *No description*
- - -
### parseNum (str)
* **str** *No description*
- - -
### prepareForWire (cs, pool)
* **cs** *No description*
* **pool** *No description*
- - -
### smartOpAssembler ()
- - -
### splitAttributionLines (attrOps, text)
* **attrOps** *No description*
* **text** *No description*
- - -
### splitTextLines (text)
* **text** *No description*
- - -
### stringAssembler ()
- - -
### stringIterator (str)
* **str** *No description*
- - -
### stringOp (str)
* **str** *No description*
- - -
### subattribution (astr, start, optEnd)
* **astr** *No description*
* **start** *No description*
* **optEnd** *No description*
- - -
### textLinesMutator (lines)
* **lines** *No description*
- - -
### toBaseTen (cs)
* **cs** *No description*
- - -
### toSplices (cs)
* **cs** *No description*
- - -
### unpack (cs)
* **cs** *No description*
##Variables
- - -
### assert
- - -
### error

View file

@ -1,24 +0,0 @@
# utils/Expo
`require("./utils/ExportHtml");`
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.
See the License for the specific language governing permissions and
limitations under the License.
## Functions
- - -
### getPadHTMLDocument (padId, revNum, noDocType, callback)
* **padId** *No description*
* **revNum** *No description*
* **noDocType** *No description*
* **callback** *No description*

View file

@ -1,16 +0,0 @@
# utils/
`require("./utils/Minify");`
This Module manages all /minified/* requests. It controls the
minification && compression of Javascript and CSS.
## Functions
- - -
### minifyJS (req, res, jsFilename)
creates the minifed javascript for the given minified name
* **req** the Express request
* **res** the Express response
* **jsFilename** *No description*

View file

@ -1,40 +0,0 @@
# utils/Se
`require("./utils/Settings");`
The Settings Modul reads the settings out of settings.json and provides
this information to the other modules
##Variables
- - -
### abiword
The path of the abiword executable
- - -
### dbSettings
This setting is passed with dbType to ueberDB to set up the database
- - -
### dbType
- - -
### defaultPadText
The default Text of a new pad
- - -
### ip
The IP ep-lite should listen to
- - -
### logHTTP
A flag that shows if http requests should be loged to stdout
- - -
### minify
A flag that shows if minification is enabled or not
- - -
### port
The Port ep-lite should listen to

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var padManager = require("./PadManager"); var padManager = require("./PadManager");
var padMessageHandler = require("../handler/PadMessageHandler"); var padMessageHandler = require("../handler/PadMessageHandler");
var readOnlyManager = require("./ReadOnlyManager"); var readOnlyManager = require("./ReadOnlyManager");
@ -109,11 +110,7 @@ exports.getText = function(padID, rev, callback)
//get the pad //get the pad
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
//the client asked for a special revision //the client asked for a special revision
if(rev !== undefined) if(rev !== undefined)
@ -128,12 +125,11 @@ exports.getText = function(padID, rev, callback)
//get the text of this revision //get the text of this revision
pad.getInternalRevisionAText(rev, function(err, atext) pad.getInternalRevisionAText(rev, function(err, atext)
{ {
if(!err) if(ERR(err, callback)) return;
{
data = {text: atext.text};
}
callback(err, data); data = {text: atext.text};
callback(null, data);
}) })
} }
//the client wants the latest text, lets return it to him //the client wants the latest text, lets return it to him
@ -158,11 +154,7 @@ exports.setText = function(padID, text, callback)
//get the pad //get the pad
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
//set the text //set the text
pad.setText(text); pad.setText(text);
@ -215,11 +207,7 @@ exports.getHTML = function(padID, rev, callback)
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
//the client asked for a special revision //the client asked for a special revision
if(rev !== undefined) if(rev !== undefined)
@ -234,11 +222,9 @@ exports.getHTML = function(padID, rev, callback)
//get the html of this revision //get the html of this revision
exportHtml.getPadHTML(pad, rev, function(err, html) exportHtml.getPadHTML(pad, rev, function(err, html)
{ {
if(!err) if(ERR(err, callback)) return;
{
data = {html: html}; data = {html: html};
} callback(null, data);
callback(err, data);
}); });
} }
//the client wants the latest text, lets return it to him //the client wants the latest text, lets return it to him
@ -246,11 +232,11 @@ exports.getHTML = function(padID, rev, callback)
{ {
exportHtml.getPadHTML(pad, undefined, function (err, html) exportHtml.getPadHTML(pad, undefined, function (err, html)
{ {
if(!err) if(ERR(err, callback)) return;
{
data = {html: html}; data = {html: html};
}
callback(err, data); callback(null, data);
}); });
} }
}); });
@ -261,11 +247,7 @@ exports.setHTML = function(padID, html, callback)
//get the pad //get the pad
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
// add a new changeset with the new html to the pad // add a new changeset with the new html to the pad
importHtml.setPadHTML(pad, cleanText(html)); importHtml.setPadHTML(pad, cleanText(html));
@ -293,11 +275,7 @@ exports.getRevisionsCount = function(padID, callback)
//get the pad //get the pad
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
callback(null, {revisions: pad.getHeadRevisionNumber()}); callback(null, {revisions: pad.getHeadRevisionNumber()});
}); });
@ -323,7 +301,8 @@ exports.createPad = function(padID, text, callback)
//create pad //create pad
getPadSafe(padID, false, text, function(err) getPadSafe(padID, false, text, function(err)
{ {
callback(err); if(ERR(err, callback)) return;
callback();
}); });
} }
@ -339,11 +318,7 @@ exports.deletePad = function(padID, callback)
{ {
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
pad.remove(callback); pad.remove(callback);
}); });
@ -362,16 +337,13 @@ exports.getReadOnlyID = function(padID, callback)
//we don't need the pad object, but this function does all the security stuff for us //we don't need the pad object, but this function does all the security stuff for us
getPadSafe(padID, true, function(err) getPadSafe(padID, true, function(err)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
//get the readonlyId //get the readonlyId
readOnlyManager.getReadOnlyId(padID, function(err, readOnlyId) readOnlyManager.getReadOnlyId(padID, function(err, readOnlyId)
{ {
callback(err, {readOnlyID: readOnlyId}); if(ERR(err, callback)) return;
callback(null, {readOnlyID: readOnlyId});
}); });
}); });
} }
@ -396,11 +368,7 @@ exports.setPublicStatus = function(padID, publicStatus, callback)
//get the pad //get the pad
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
//convert string to boolean //convert string to boolean
if(typeof publicStatus == "string") if(typeof publicStatus == "string")
@ -433,11 +401,7 @@ exports.getPublicStatus = function(padID, callback)
//get the pad //get the pad
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
callback(null, {publicStatus: pad.getPublicStatus()}); callback(null, {publicStatus: pad.getPublicStatus()});
}); });
@ -463,11 +427,7 @@ exports.setPassword = function(padID, password, callback)
//get the pad //get the pad
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
//set the password //set the password
pad.setPassword(password); pad.setPassword(password);
@ -496,11 +456,7 @@ exports.isPasswordProtected = function(padID, callback)
//get the pad //get the pad
getPadSafe(padID, true, function(err, pad) getPadSafe(padID, true, function(err, pad)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
callback(null, {isPasswordProtected: pad.isPasswordProtected()}); callback(null, {isPasswordProtected: pad.isPasswordProtected()});
}); });
@ -542,13 +498,10 @@ function getPadSafe(padID, shouldExist, text, callback)
//check if the pad exists //check if the pad exists
padManager.doesPadExists(padID, function(err, exists) padManager.doesPadExists(padID, function(err, exists)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//does not exist, but should //does not exist, but should
else if(exists == false && shouldExist == true) if(exists == false && shouldExist == true)
{ {
callback({stop: "padID does not exist"}); callback({stop: "padID does not exist"});
} }

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var db = require("./DB").db; var db = require("./DB").db;
var async = require("async"); var async = require("async");
@ -29,7 +30,8 @@ exports.doesAuthorExists = function (authorID, callback)
//check if the database entry of this author exists //check if the database entry of this author exists
db.get("globalAuthor:" + authorID, function (err, author) db.get("globalAuthor:" + authorID, function (err, author)
{ {
callback(err, author != null); if(ERR(err, callback)) return;
callback(null, author != null);
}); });
} }
@ -42,8 +44,9 @@ exports.getAuthor4Token = function (token, callback)
{ {
mapAuthorWithDBKey("token2author", token, function(err, author) mapAuthorWithDBKey("token2author", token, function(err, author)
{ {
if(ERR(err, callback)) return;
//return only the sub value authorID //return only the sub value authorID
callback(err, author ? author.authorID : author); callback(null, author ? author.authorID : author);
}); });
} }
@ -56,12 +59,7 @@ exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback)
{ {
mapAuthorWithDBKey("mapper2author", authorMapper, function(err, author) mapAuthorWithDBKey("mapper2author", authorMapper, function(err, author)
{ {
//error? if(ERR(err, callback)) return;
if(err)
{
callback(err);
return;
}
//set the name of this author //set the name of this author
if(name) if(name)
@ -84,24 +82,14 @@ function mapAuthorWithDBKey (mapperkey, mapper, callback)
//try to map to an author //try to map to an author
db.get(mapperkey + ":" + mapper, function (err, author) db.get(mapperkey + ":" + mapper, function (err, author)
{ {
//error? if(ERR(err, callback)) return;
if(err)
{
callback(err);
return;
}
//there is no author with this mapper, so create one //there is no author with this mapper, so create one
if(author == null) if(author == null)
{ {
exports.createAuthor(null, function(err, author) exports.createAuthor(null, function(err, author)
{ {
//error? if(ERR(err, callback)) return;
if(err)
{
callback(err);
return;
}
//create the token2author relation //create the token2author relation
db.set(mapperkey + ":" + mapper, author.authorID); db.set(mapperkey + ":" + mapper, author.authorID);

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var db = require("./DB").db; var db = require("./DB").db;
var async = require("async"); var async = require("async");
var padManager = require("./PadManager"); var padManager = require("./PadManager");
@ -34,13 +35,10 @@ exports.deleteGroup = function(groupID, callback)
//try to get the group entry //try to get the group entry
db.get("group:" + groupID, function (err, _group) db.get("group:" + groupID, function (err, _group)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//group does not exist //group does not exist
else if(_group == null) if(_group == null)
{ {
callback({stop: "groupID does not exist"}); callback({stop: "groupID does not exist"});
} }
@ -67,7 +65,7 @@ exports.deleteGroup = function(groupID, callback)
{ {
padManager.getPad(padID, function(err, pad) padManager.getPad(padID, function(err, pad)
{ {
if(err) {callback(err); return} if(ERR(err, callback)) return;
pad.remove(callback); pad.remove(callback);
}); });
@ -79,7 +77,7 @@ exports.deleteGroup = function(groupID, callback)
//try to get the group entry //try to get the group entry
db.get("group2sessions:" + groupID, function (err, group2sessions) db.get("group2sessions:" + groupID, function (err, group2sessions)
{ {
if(err) {callback(err); return} if(ERR(err, callback)) return;
//skip if there is no group2sessions entry //skip if there is no group2sessions entry
if(group2sessions == null) {callback(); return} if(group2sessions == null) {callback(); return}
@ -107,7 +105,8 @@ exports.deleteGroup = function(groupID, callback)
} }
], function(err) ], function(err)
{ {
callback(err); if(ERR(err, callback)) return;
callback();
}); });
} }
@ -116,7 +115,8 @@ exports.doesGroupExist = function(groupID, callback)
//try to get the group entry //try to get the group entry
db.get("group:" + groupID, function (err, group) db.get("group:" + groupID, function (err, group)
{ {
callback(err, group != null); if(ERR(err, callback)) return;
callback(null, group != null);
}); });
} }
@ -142,23 +142,14 @@ exports.createGroupIfNotExistsFor = function(groupMapper, callback)
//try to get a group for this mapper //try to get a group for this mapper
db.get("mapper2group:"+groupMapper, function(err, groupID) db.get("mapper2group:"+groupMapper, function(err, groupID)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
//there is no group for this mapper, let's create a group //there is no group for this mapper, let's create a group
if(groupID == null) if(groupID == null)
{ {
exports.createGroup(function(err, responseObj) exports.createGroup(function(err, responseObj)
{ {
//check for errors if(ERR(err, callback)) return;
if(err)
{
callback(err);
return;
}
//create the mapper entry for this group //create the mapper entry for this group
db.set("mapper2group:"+groupMapper, responseObj.groupID); db.set("mapper2group:"+groupMapper, responseObj.groupID);
@ -169,7 +160,8 @@ exports.createGroupIfNotExistsFor = function(groupMapper, callback)
//there is a group for this mapper, let's return it //there is a group for this mapper, let's return it
else else
{ {
callback(err, {groupID: groupID}); if(ERR(err, callback)) return;
callback(null, {groupID: groupID});
} }
}); });
} }
@ -185,13 +177,10 @@ exports.createGroupPad = function(groupID, padName, text, callback)
{ {
exports.doesGroupExist(groupID, function(err, exists) exports.doesGroupExist(groupID, function(err, exists)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//group does not exist //group does not exist
else if(exists == false) if(exists == false)
{ {
callback({stop: "groupID does not exist"}); callback({stop: "groupID does not exist"});
} }
@ -207,13 +196,10 @@ exports.createGroupPad = function(groupID, padName, text, callback)
{ {
padManager.doesPadExists(padID, function(err, exists) padManager.doesPadExists(padID, function(err, exists)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//pad exists already //pad exists already
else if(exists == true) if(exists == true)
{ {
callback({stop: "padName does already exist"}); callback({stop: "padName does already exist"});
} }
@ -229,7 +215,8 @@ exports.createGroupPad = function(groupID, padName, text, callback)
{ {
padManager.getPad(padID, text, function(err) padManager.getPad(padID, text, function(err)
{ {
callback(err); if(ERR(err, callback)) return;
callback();
}); });
}, },
//create an entry in the group for this pad //create an entry in the group for this pad
@ -240,7 +227,8 @@ exports.createGroupPad = function(groupID, padName, text, callback)
} }
], function(err) ], function(err)
{ {
callback(err, {padID: padID}); if(ERR(err, callback)) return;
callback(null, {padID: padID});
}); });
} }
@ -248,13 +236,10 @@ exports.listPads = function(groupID, callback)
{ {
exports.doesGroupExist(groupID, function(err, exists) exports.doesGroupExist(groupID, function(err, exists)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//group does not exist //group does not exist
else if(exists == false) if(exists == false)
{ {
callback({stop: "groupID does not exist"}); callback({stop: "groupID does not exist"});
} }
@ -263,7 +248,8 @@ exports.listPads = function(groupID, callback)
{ {
db.getSub("group:" + groupID, ["pads"], function(err, pads) db.getSub("group:" + groupID, ["pads"], function(err, pads)
{ {
callback(err, {padIDs: pads}); if(ERR(err, callback)) return;
callback(null, {padIDs: pads});
}); });
} }
}); });

View file

@ -4,6 +4,7 @@
require('joose'); require('joose');
var ERR = require("async-stacktrace");
var Changeset = require("../utils/Changeset"); var Changeset = require("../utils/Changeset");
var AttributePoolFactory = require("../utils/AttributePoolFactory"); var AttributePoolFactory = require("../utils/AttributePoolFactory");
var db = require("./DB").db; var db = require("./DB").db;
@ -164,8 +165,9 @@ Class('Pad', {
{ {
db.getSub("pad:"+_this.id+":revs:"+keyRev, ["meta", "atext"], function(err, _atext) db.getSub("pad:"+_this.id+":revs:"+keyRev, ["meta", "atext"], function(err, _atext)
{ {
if(ERR(err, callback)) return;
atext = Changeset.cloneAText(_atext); atext = Changeset.cloneAText(_atext);
callback(err); callback();
}); });
}, },
//get all needed changesets //get all needed changesets
@ -175,8 +177,9 @@ Class('Pad', {
{ {
_this.getRevisionChangeset(item, function(err, changeset) _this.getRevisionChangeset(item, function(err, changeset)
{ {
if(ERR(err, callback)) return;
changesets[item] = changeset; changesets[item] = changeset;
callback(err); callback();
}); });
}, callback); }, callback);
} }
@ -199,7 +202,8 @@ Class('Pad', {
} }
], function(err) ], function(err)
{ {
callback(err, atext); if(ERR(err, callback)) return;
callback(null, atext);
}); });
}, },
@ -247,8 +251,9 @@ Class('Pad', {
{ {
db.get("pad:"+_this.id+":chat:"+entryNum, function(err, _entry) db.get("pad:"+_this.id+":chat:"+entryNum, function(err, _entry)
{ {
if(ERR(err, callback)) return;
entry = _entry; entry = _entry;
callback(err); callback();
}); });
}, },
//add the authorName //add the authorName
@ -264,13 +269,15 @@ Class('Pad', {
//get the authorName //get the authorName
authorManager.getAuthorName(entry.userId, function(err, authorName) authorManager.getAuthorName(entry.userId, function(err, authorName)
{ {
if(ERR(err, callback)) return;
entry.userName = authorName; entry.userName = authorName;
callback(err); callback();
}); });
} }
], function(err) ], function(err)
{ {
callback(err, entry); if(ERR(err, callback)) return;
callback(null, entry);
}); });
}, },
@ -311,11 +318,14 @@ Class('Pad', {
{ {
_this.getChatMessage(entryObject.entryNum, function(err, entry) _this.getChatMessage(entryObject.entryNum, function(err, entry)
{ {
if(ERR(err, callback)) return;
entries[entryObject.order] = entry; entries[entryObject.order] = entry;
callback(err); callback();
}); });
}, function(err) }, function(err)
{ {
if(ERR(err, callback)) return;
//sort out broken chat entries //sort out broken chat entries
//it looks like in happend in the past that the chat head was //it looks like in happend in the past that the chat head was
//incremented, but the chat message wasn't added //incremented, but the chat message wasn't added
@ -328,7 +338,7 @@ Class('Pad', {
console.warn("WARNING: Found broken chat entry in pad " + _this.id); console.warn("WARNING: Found broken chat entry in pad " + _this.id);
} }
callback(err, cleanedEntries); callback(null, cleanedEntries);
}); });
}, },
@ -345,11 +355,7 @@ Class('Pad', {
//try to load the pad //try to load the pad
db.get("pad:"+this.id, function(err, value) db.get("pad:"+this.id, function(err, value)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err, null);
return;
}
//if this pad exists, load it //if this pad exists, load it
if(value != null) if(value != null)
@ -410,7 +416,7 @@ Class('Pad', {
db.get("group:" + groupID, function (err, group) db.get("group:" + groupID, function (err, group)
{ {
if(err) {callback(err); return} if(ERR(err, callback)) return;
//remove the pad entry //remove the pad entry
delete group.pads[padID]; delete group.pads[padID];
@ -432,7 +438,7 @@ Class('Pad', {
{ {
readOnlyManager.getReadOnlyId(padID, function(err, readonlyID) readOnlyManager.getReadOnlyId(padID, function(err, readonlyID)
{ {
if(err) {callback(err); return} if(ERR(err, callback)) return;
db.remove("pad2readonly:" + padID); db.remove("pad2readonly:" + padID);
db.remove("readonly2pad:" + readonlyID); db.remove("readonly2pad:" + readonlyID);
@ -475,7 +481,8 @@ Class('Pad', {
} }
], function(err) ], function(err)
{ {
callback(err); if(ERR(err, callback)) return;
callback();
}) })
}, },
//set in db //set in db

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
require("../db/Pad"); require("../db/Pad");
var db = require("./DB").db; var db = require("./DB").db;
@ -90,15 +91,10 @@ exports.getPad = function(id, text, callback)
//initalize the pad //initalize the pad
pad.init(text, function(err) pad.init(text, function(err)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err, null);
}
else
{
globalPads.set(id, pad); globalPads.set(id, pad);
callback(null, pad); callback(null, pad);
}
}); });
} }
} }
@ -108,7 +104,8 @@ exports.doesPadExists = function(padId, callback)
{ {
db.get("pad:"+padId, function(err, value) db.get("pad:"+padId, function(err, value)
{ {
callback(err, value != null); if(ERR(err, callback)) return;
callback(null, value != null);
}); });
} }

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var db = require("./DB").db; var db = require("./DB").db;
var async = require("async"); var async = require("async");
@ -55,8 +56,9 @@ exports.getReadOnlyId = function (padId, callback)
} }
], function(err) ], function(err)
{ {
if(ERR(err, callback)) return;
//return the results //return the results
callback(err, readOnlyId); callback(null, readOnlyId);
}) })
} }

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var db = require("./DB").db; var db = require("./DB").db;
var async = require("async"); var async = require("async");
var authorManager = require("./AuthorManager"); var authorManager = require("./AuthorManager");
@ -56,6 +57,8 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
//get author for this token //get author for this token
authorManager.getAuthor4Token(token, function(err, author) authorManager.getAuthor4Token(token, function(err, author)
{ {
if(ERR(err, callback)) return;
// assume user has access // assume user has access
statusObject = {accessStatus: "grant", authorID: author}; statusObject = {accessStatus: "grant", authorID: author};
// user can't create pads // user can't create pads
@ -64,17 +67,19 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
// check if pad exists // check if pad exists
padManager.doesPadExists(padID, function(err, exists) padManager.doesPadExists(padID, function(err, exists)
{ {
if(ERR(err, callback)) return;
// pad doesn't exist - user can't have access // pad doesn't exist - user can't have access
if(!exists) statusObject.accessStatus = "deny"; if(!exists) statusObject.accessStatus = "deny";
// grant or deny access, with author of token // grant or deny access, with author of token
callback(err, statusObject); callback(null, statusObject);
}); });
} }
// user may create new pads - no need to check anything // user may create new pads - no need to check anything
else else
{ {
// grant access, with author of token // grant access, with author of token
callback(err, statusObject); callback(null, statusObject);
} }
}) })
@ -102,8 +107,9 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
{ {
padManager.doesPadExists(padID, function(err, exists) padManager.doesPadExists(padID, function(err, exists)
{ {
if(ERR(err, callback)) return;
padExists = exists; padExists = exists;
callback(err); callback();
}); });
}, },
//get informations about this session //get informations about this session
@ -118,7 +124,7 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
return; return;
} }
if(err) {callback(err); return} if(ERR(err, callback)) return;
var now = Math.floor(new Date().getTime()/1000); var now = Math.floor(new Date().getTime()/1000);
@ -139,8 +145,9 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
//get author for this token //get author for this token
authorManager.getAuthor4Token(token, function(err, author) authorManager.getAuthor4Token(token, function(err, author)
{ {
if(ERR(err, callback)) return;
tokenAuthor = author; tokenAuthor = author;
callback(err); callback();
}); });
} }
], callback); ], callback);
@ -157,7 +164,7 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
padManager.getPad(padID, function(err, pad) padManager.getPad(padID, function(err, pad)
{ {
if(err) {callback(err); return} if(ERR(err, callback)) return;
//is it a public pad? //is it a public pad?
isPublic = pad.getPublicStatus(); isPublic = pad.getPublicStatus();
@ -265,6 +272,7 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
} }
], function(err) ], function(err)
{ {
callback(err, statusObject); if(ERR(err, callback)) return;
callback(null, statusObject);
}); });
} }

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var db = require("./DB").db; var db = require("./DB").db;
var async = require("async"); var async = require("async");
var groupMangager = require("./GroupManager"); var groupMangager = require("./GroupManager");
@ -28,7 +29,8 @@ exports.doesSessionExist = function(sessionID, callback)
//check if the database entry of this session exists //check if the database entry of this session exists
db.get("session:" + sessionID, function (err, session) db.get("session:" + sessionID, function (err, session)
{ {
callback(err, session != null); if(ERR(err, callback)) return;
callback(null, session != null);
}); });
} }
@ -45,13 +47,10 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
{ {
groupMangager.doesGroupExist(groupID, function(err, exists) groupMangager.doesGroupExist(groupID, function(err, exists)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//group does not exist //group does not exist
else if(exists == false) if(exists == false)
{ {
callback({stop: "groupID does not exist"}); callback({stop: "groupID does not exist"});
} }
@ -67,13 +66,10 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
{ {
authorMangager.doesAuthorExists(authorID, function(err, exists) authorMangager.doesAuthorExists(authorID, function(err, exists)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//author does not exist //author does not exist
else if(exists == false) if(exists == false)
{ {
callback({stop: "authorID does not exist"}); callback({stop: "authorID does not exist"});
} }
@ -137,12 +133,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
//get the entry //get the entry
db.get("group2sessions:" + groupID, function(err, group2sessions) db.get("group2sessions:" + groupID, function(err, group2sessions)
{ {
//did a error happen? if(ERR(err, callback)) return;
if(err)
{
callback(err);
return;
}
//the entry doesn't exist so far, let's create it //the entry doesn't exist so far, let's create it
if(group2sessions == null) if(group2sessions == null)
@ -165,12 +156,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
//get the entry //get the entry
db.get("author2sessions:" + authorID, function(err, author2sessions) db.get("author2sessions:" + authorID, function(err, author2sessions)
{ {
//did a error happen? if(ERR(err, callback)) return;
if(err)
{
callback(err);
return;
}
//the entry doesn't exist so far, let's create it //the entry doesn't exist so far, let's create it
if(author2sessions == null) if(author2sessions == null)
@ -189,8 +175,10 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
} }
], function(err) ], function(err)
{ {
if(ERR(err, callback)) return;
//return error and sessionID //return error and sessionID
callback(err, {sessionID: sessionID}); callback(null, {sessionID: sessionID});
}) })
} }
@ -199,13 +187,10 @@ exports.getSessionInfo = function(sessionID, callback)
//check if the database entry of this session exists //check if the database entry of this session exists
db.get("session:" + sessionID, function (err, session) db.get("session:" + sessionID, function (err, session)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//session does not exists //session does not exists
else if(session == null) if(session == null)
{ {
callback({stop: "sessionID does not exist"}) callback({stop: "sessionID does not exist"})
} }
@ -231,13 +216,10 @@ exports.deleteSession = function(sessionID, callback)
//get the session entry //get the session entry
db.get("session:" + sessionID, function (err, session) db.get("session:" + sessionID, function (err, session)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//session does not exists //session does not exists
else if(session == null) if(session == null)
{ {
callback({stop: "sessionID does not exist"}) callback({stop: "sessionID does not exist"})
} }
@ -256,8 +238,9 @@ exports.deleteSession = function(sessionID, callback)
{ {
db.get("group2sessions:" + groupID, function (err, _group2sessions) db.get("group2sessions:" + groupID, function (err, _group2sessions)
{ {
if(ERR(err, callback)) return;
group2sessions = _group2sessions; group2sessions = _group2sessions;
callback(err); callback();
}); });
}, },
//get the author2sessions entry //get the author2sessions entry
@ -265,8 +248,9 @@ exports.deleteSession = function(sessionID, callback)
{ {
db.get("author2sessions:" + authorID, function (err, _author2sessions) db.get("author2sessions:" + authorID, function (err, _author2sessions)
{ {
if(ERR(err, callback)) return;
author2sessions = _author2sessions; author2sessions = _author2sessions;
callback(err); callback();
}); });
}, },
//remove the values from the database //remove the values from the database
@ -287,7 +271,8 @@ exports.deleteSession = function(sessionID, callback)
} }
], function(err) ], function(err)
{ {
callback(err); if(ERR(err, callback)) return;
callback();
}) })
} }
@ -295,13 +280,10 @@ exports.listSessionsOfGroup = function(groupID, callback)
{ {
groupMangager.doesGroupExist(groupID, function(err, exists) groupMangager.doesGroupExist(groupID, function(err, exists)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//group does not exist //group does not exist
else if(exists == false) if(exists == false)
{ {
callback({stop: "groupID does not exist"}); callback({stop: "groupID does not exist"});
} }
@ -317,13 +299,10 @@ exports.listSessionsOfAuthor = function(authorID, callback)
{ {
authorMangager.doesAuthorExists(authorID, function(err, exists) authorMangager.doesAuthorExists(authorID, function(err, exists)
{ {
//error if(ERR(err, callback)) return;
if(err)
{
callback(err);
}
//group does not exist //group does not exist
else if(exists == false) if(exists == false)
{ {
callback({stop: "authorID does not exist"}); callback({stop: "authorID does not exist"});
} }
@ -346,8 +325,9 @@ function listSessionsWithDBKey (dbkey, callback)
//get the group2sessions entry //get the group2sessions entry
db.get(dbkey, function(err, sessionObject) db.get(dbkey, function(err, sessionObject)
{ {
if(ERR(err, callback)) return;
sessions = sessionObject ? sessionObject.sessionIDs : null; sessions = sessionObject ? sessionObject.sessionIDs : null;
callback(err); callback();
}); });
}, },
function(callback) function(callback)
@ -364,14 +344,16 @@ function listSessionsWithDBKey (dbkey, callback)
{ {
exports.getSessionInfo(sessionID, function(err, sessionInfo) exports.getSessionInfo(sessionID, function(err, sessionInfo)
{ {
if(ERR(err, callback)) return;
sessions[sessionID] = sessionInfo; sessions[sessionID] = sessionInfo;
callback(err); callback();
}); });
}, callback); }, callback);
} }
], function(err) ], function(err)
{ {
callback(err, sessions); if(ERR(err, callback)) return;
callback(null, sessions);
}); });
} }

View file

@ -20,8 +20,8 @@
* limitations under the License. * limitations under the License.
*/ */
var Changeset = require('./Changeset'); var Changeset = require('./utils/Changeset');
var AttributePoolFactory = require("./AttributePoolFactory"); var AttributePoolFactory = require("./utils/AttributePoolFactory");
function random() { function random() {
this.nextInt = function (maxValue) { this.nextInt = function (maxValue) {

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var fs = require("fs"); var fs = require("fs");
var api = require("../db/API"); var api = require("../db/API");
@ -122,7 +123,7 @@ exports.handle = function(functionName, fields, req, res)
else else
{ {
res.send({code: 2, message: "internal error", data: null}); res.send({code: 2, message: "internal error", data: null});
throw (err); ERR(err);
} }
}); });

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var exporthtml = require("../utils/ExportHtml"); var exporthtml = require("../utils/ExportHtml");
var padManager = require("../db/PadManager"); var padManager = require("../db/PadManager");
var async = require("async"); var async = require("async");
@ -50,8 +51,7 @@ exports.doExport = function(req, res, padId, type)
{ {
padManager.getPad(padId, function(err, pad) padManager.getPad(padId, function(err, pad)
{ {
if(err) ERR(err);
throw err;
res.send(pad.text()); res.send(pad.text());
}); });
@ -68,8 +68,9 @@ exports.doExport = function(req, res, padId, type)
{ {
exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html) exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
{ {
if(ERR(err, callback)) return;
html = _html; html = _html;
callback(err); callback();
}); });
}, },
//decide what to do with the html export //decide what to do with the html export
@ -120,12 +121,16 @@ exports.doExport = function(req, res, padId, type)
fs.unlink(destFile, callback); fs.unlink(destFile, callback);
}, 100); }, 100);
} }
else
{
fs.unlink(destFile, callback);
}
} }
], callback); ], callback);
} }
], function(err) ], function(err)
{ {
if(err && err != "stop") throw err; if(err && err != "stop") ERR(err);
}) })
} }
}; };

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var padManager = require("../db/PadManager"); var padManager = require("../db/PadManager");
var padMessageHandler = require("./PadMessageHandler"); var padMessageHandler = require("./PadMessageHandler");
var async = require("async"); var async = require("async");
@ -122,8 +123,9 @@ exports.doImport = function(req, res, padId)
{ {
padManager.getPad(padId, function(err, _pad) padManager.getPad(padId, function(err, _pad)
{ {
if(ERR(err, callback)) return;
pad = _pad; pad = _pad;
callback(err); callback();
}); });
}, },
@ -132,6 +134,7 @@ exports.doImport = function(req, res, padId)
{ {
fs.readFile(destFile, "utf8", function(err, _text) fs.readFile(destFile, "utf8", function(err, _text)
{ {
if(ERR(err, callback)) return;
text = _text; 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.
@ -140,9 +143,13 @@ exports.doImport = function(req, res, padId)
{ {
setTimeout(function() setTimeout(function()
{ {
callback(err); callback();
}, 100); }, 100);
} }
else
{
callback();
}
}); });
}, },
@ -176,7 +183,7 @@ exports.doImport = function(req, res, padId)
return; return;
} }
if(err) throw err; ERR(err);
//close the connection //close the connection
res.send("ok"); res.send("ok");

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var async = require("async"); var async = require("async");
var padManager = require("../db/PadManager"); var padManager = require("../db/PadManager");
var Changeset = require("../utils/Changeset"); var Changeset = require("../utils/Changeset");
@ -107,7 +108,7 @@ exports.handleDisconnect = function(client)
//get the author color out of the db //get the author color out of the db
authorManager.getAuthorColorId(author, function(err, color) authorManager.getAuthorColorId(author, function(err, color)
{ {
if(err) throw err; ERR(err);
//prepare the notification for the other users on the pad, that this user left //prepare the notification for the other users on the pad, that this user left
var messageToTheOtherUsers = { var messageToTheOtherUsers = {
@ -218,16 +219,18 @@ function handleChatMessage(client, message)
{ {
padManager.getPad(padId, function(err, _pad) padManager.getPad(padId, function(err, _pad)
{ {
if(ERR(err, callback)) return;
pad = _pad; pad = _pad;
callback(err); callback();
}); });
}, },
function(callback) function(callback)
{ {
authorManager.getAuthorName(userId, function(err, _userName) authorManager.getAuthorName(userId, function(err, _userName)
{ {
if(ERR(err, callback)) return;
userName = _userName; userName = _userName;
callback(err); callback();
}); });
}, },
//save the chat message and broadcast it //save the chat message and broadcast it
@ -257,7 +260,7 @@ function handleChatMessage(client, message)
} }
], function(err) ], function(err)
{ {
if(err) throw err; ERR(err);
}); });
} }
@ -375,8 +378,9 @@ function handleUserChanges(client, message)
{ {
padManager.getPad(session2pad[client.id], function(err, value) padManager.getPad(session2pad[client.id], function(err, value)
{ {
if(ERR(err, callback)) return;
pad = value; pad = value;
callback(err); callback();
}); });
}, },
//create the changeset //create the changeset
@ -422,16 +426,10 @@ function handleUserChanges(client, message)
pad.getRevisionChangeset(r, function(err, c) pad.getRevisionChangeset(r, function(err, c)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
else
{
changeset = Changeset.follow(c, changeset, false, apool); changeset = Changeset.follow(c, changeset, false, apool);
callback(null); callback(null);
}
}); });
}, },
//use the callback of the series function //use the callback of the series function
@ -469,7 +467,7 @@ function handleUserChanges(client, message)
} }
], function(err) ], function(err)
{ {
if(err) throw err; ERR(err);
}); });
} }
@ -502,25 +500,23 @@ exports.updatePadClients = function(pad, callback)
{ {
pad.getRevisionAuthor(r, function(err, value) pad.getRevisionAuthor(r, function(err, value)
{ {
if(ERR(err, callback)) return;
author = value; author = value;
callback(err); callback();
}); });
}, },
function (callback) function (callback)
{ {
pad.getRevisionChangeset(r, function(err, value) pad.getRevisionChangeset(r, function(err, value)
{ {
if(ERR(err, callback)) return;
revChangeset = value; revChangeset = value;
callback(err); callback();
}); });
} }
], function(err) ], function(err)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
if(author == sessioninfos[session].author) if(author == sessioninfos[session].author)
{ {
@ -633,7 +629,7 @@ function handleClientReady(client, message)
{ {
securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject) securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject)
{ {
if(err) {callback(err); return} if(ERR(err, callback)) return;
//access was granted //access was granted
if(statusObject.accessStatus == "grant") if(statusObject.accessStatus == "grant")
@ -657,8 +653,9 @@ function handleClientReady(client, message)
{ {
authorManager.getAuthorColorId(author, function(err, value) authorManager.getAuthorColorId(author, function(err, value)
{ {
if(ERR(err, callback)) return;
authorColorId = value; authorColorId = value;
callback(err); callback();
}); });
}, },
//get author name //get author name
@ -666,24 +663,27 @@ function handleClientReady(client, message)
{ {
authorManager.getAuthorName(author, function(err, value) authorManager.getAuthorName(author, function(err, value)
{ {
if(ERR(err, callback)) return;
authorName = value; authorName = value;
callback(err); callback();
}); });
}, },
function(callback) function(callback)
{ {
padManager.getPad(message.padId, function(err, value) padManager.getPad(message.padId, function(err, value)
{ {
if(ERR(err, callback)) return;
pad = value; pad = value;
callback(err); callback();
}); });
}, },
function(callback) function(callback)
{ {
readOnlyManager.getReadOnlyId(message.padId, function(err, value) readOnlyManager.getReadOnlyId(message.padId, function(err, value)
{ {
if(ERR(err, callback)) return;
readOnlyId = value; readOnlyId = value;
callback(err); callback();
}); });
} }
], callback); ], callback);
@ -701,9 +701,10 @@ function handleClientReady(client, message)
{ {
authorManager.getAuthor(authorId, function(err, author) authorManager.getAuthor(authorId, function(err, author)
{ {
if(ERR(err, callback)) return;
delete author.timestamp; delete author.timestamp;
historicalAuthorData[authorId] = author; historicalAuthorData[authorId] = author;
callback(err); callback();
}); });
}, callback); }, callback);
}, },
@ -712,8 +713,9 @@ function handleClientReady(client, message)
{ {
pad.getLastChatMessages(100, function(err, _chatMessages) pad.getLastChatMessages(100, function(err, _chatMessages)
{ {
if(ERR(err, callback)) return;
chatMessages = _chatMessages; chatMessages = _chatMessages;
callback(err); callback();
}); });
} }
], callback); ], callback);
@ -806,6 +808,8 @@ function handleClientReady(client, message)
clientVars.userName = authorName; clientVars.userName = authorName;
} }
if(sessioninfos[client.id] !== undefined)
{
//This is a reconnect, so we don't have to send the client the ClientVars again //This is a reconnect, so we don't have to send the client the ClientVars again
if(message.reconnect == true) if(message.reconnect == true)
{ {
@ -822,8 +826,8 @@ function handleClientReady(client, message)
} }
//Save the revision and the author id in sessioninfos //Save the revision and the author id in sessioninfos
sessioninfos[client.id].rev = pad.getHeadRevisionNumber();
sessioninfos[client.id].author = author; sessioninfos[client.id].author = author;
}
//prepare the notification for the other users on the pad, that this user joined //prepare the notification for the other users on the pad, that this user joined
var messageToTheOtherUsers = { var messageToTheOtherUsers = {
@ -859,16 +863,18 @@ function handleClientReady(client, message)
{ {
authorManager.getAuthorColorId(sessioninfos[sessionID].author, function(err, value) authorManager.getAuthorColorId(sessioninfos[sessionID].author, function(err, value)
{ {
if(ERR(err, callback)) return;
sessionAuthorColorId = value; sessionAuthorColorId = value;
callback(err); callback();
}) })
}, },
function(callback) function(callback)
{ {
authorManager.getAuthorName(sessioninfos[sessionID].author, function(err, value) authorManager.getAuthorName(sessioninfos[sessionID].author, function(err, value)
{ {
if(ERR(err, callback)) return;
sessionAuthorName = value; sessionAuthorName = value;
callback(err); callback();
}) })
} }
],callback); ],callback);
@ -903,6 +909,6 @@ function handleClientReady(client, message)
} }
],function(err) ],function(err)
{ {
if(err) throw err; ERR(err);
}); });
} }

View file

@ -19,6 +19,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var log4js = require('log4js'); var log4js = require('log4js');
var messageLogger = log4js.getLogger("message"); var messageLogger = log4js.getLogger("message");
var securityManager = require("../db/SecurityManager"); var securityManager = require("../db/SecurityManager");
@ -109,7 +110,7 @@ exports.setSocketIO = function(_socket)
{ {
securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject) securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject)
{ {
if(err) throw err; ERR(err);
//access was granted, mark the client as authorized and handle the message //access was granted, mark the client as authorized and handle the message
if(statusObject.accessStatus == "grant") if(statusObject.accessStatus == "grant")

View file

@ -18,6 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var async = require("async"); var async = require("async");
var padManager = require("../db/PadManager"); var padManager = require("../db/PadManager");
var Changeset = require("../utils/Changeset"); var Changeset = require("../utils/Changeset");
@ -92,7 +93,7 @@ function handleClientReady(client, message)
//send the timeslider client the clientVars, with this values its able to start //send the timeslider client the clientVars, with this values its able to start
createTimesliderClientVars (message.padId, function(err, clientVars) createTimesliderClientVars (message.padId, function(err, clientVars)
{ {
if(err) throw err; ERR(err);
client.json.send({type: "CLIENT_VARS", data: clientVars}); client.json.send({type: "CLIENT_VARS", data: clientVars});
}) })
@ -138,7 +139,7 @@ function handleChangesetRequest(client, message)
//build the requested rough changesets and send them back //build the requested rough changesets and send them back
getChangesetInfo(padId, start, end, granularity, function(err, changesetInfo) getChangesetInfo(padId, start, end, granularity, function(err, changesetInfo)
{ {
if(err) throw err; ERR(err);
var data = changesetInfo; var data = changesetInfo;
data.requestID = message.data.requestID; data.requestID = message.data.requestID;
@ -171,8 +172,9 @@ function createTimesliderClientVars (padId, callback)
{ {
padManager.getPad(padId, function(err, _pad) padManager.getPad(padId, function(err, _pad)
{ {
if(ERR(err, callback)) return;
pad = _pad; pad = _pad;
callback(err); callback();
}); });
}, },
//get all authors and add them to //get all authors and add them to
@ -187,15 +189,17 @@ function createTimesliderClientVars (padId, callback)
{ {
authorManager.getAuthor(authorId, function(err, author) authorManager.getAuthor(authorId, function(err, author)
{ {
if(ERR(err, callback)) return;
historicalAuthorData[authorId] = author; historicalAuthorData[authorId] = author;
callback(err); callback();
}); });
}, function(err) }, function(err)
{ {
if(ERR(err, callback)) return;
//add historicalAuthorData to the clientVars and continue //add historicalAuthorData to the clientVars and continue
clientVars.historicalAuthorData = historicalAuthorData; clientVars.historicalAuthorData = historicalAuthorData;
clientVars.initialStyledContents.historicalAuthorData = historicalAuthorData; clientVars.initialStyledContents.historicalAuthorData = historicalAuthorData;
callback(err); callback();
}); });
}, },
//get the timestamp of the last revision //get the timestamp of the last revision
@ -203,8 +207,9 @@ function createTimesliderClientVars (padId, callback)
{ {
pad.getRevisionDate(pad.getHeadRevisionNumber(), function(err, date) pad.getRevisionDate(pad.getHeadRevisionNumber(), function(err, date)
{ {
if(ERR(err, callback)) return;
clientVars.currentTime = date; clientVars.currentTime = date;
callback(err); callback();
}); });
}, },
function(callback) function(callback)
@ -235,14 +240,16 @@ function createTimesliderClientVars (padId, callback)
Math.floor(lastRev / topGranularity)*topGranularity+topGranularity, granularity, Math.floor(lastRev / topGranularity)*topGranularity+topGranularity, granularity,
function(err, changeset) function(err, changeset)
{ {
if(ERR(err, callback)) return;
clientVars.initialChangesets.push(changeset); clientVars.initialChangesets.push(changeset);
callback(err); callback();
}); });
}, callback); }, callback);
} }
], function(err) ], function(err)
{ {
callback(err, clientVars); if(ERR(err, callback)) return;
callback(null, clientVars);
}); });
} }
@ -267,8 +274,9 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
{ {
padManager.getPad(padId, function(err, _pad) padManager.getPad(padId, function(err, _pad)
{ {
if(ERR(err, callback)) return;
pad = _pad; pad = _pad;
callback(err); callback();
}); });
}, },
function(callback) function(callback)
@ -309,8 +317,9 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
{ {
composePadChangesets(padId, item.start, item.end, function(err, changeset) composePadChangesets(padId, item.start, item.end, function(err, changeset)
{ {
if(ERR(err, callback)) return;
composedChangesets[item.start + "/" + item.end] = changeset; composedChangesets[item.start + "/" + item.end] = changeset;
callback(err); callback();
}); });
}, callback); }, callback);
}, },
@ -321,8 +330,9 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
{ {
pad.getRevisionDate(revNum, function(err, revDate) pad.getRevisionDate(revNum, function(err, revDate)
{ {
if(ERR(err, callback)) return;
revisionDate[revNum] = Math.floor(revDate/1000); revisionDate[revNum] = Math.floor(revDate/1000);
callback(err); callback();
}); });
}, callback); }, callback);
}, },
@ -331,8 +341,9 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
{ {
getPadLines(padId, startNum-1, function(err, _lines) getPadLines(padId, startNum-1, function(err, _lines)
{ {
if(ERR(err, callback)) return;
lines = _lines; lines = _lines;
callback(err); callback();
}); });
} }
], callback); ], callback);
@ -383,12 +394,8 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
} }
], function(err) ], function(err)
{ {
if(err) if(ERR(err, callback)) return;
{
callback(err);
}
else
{
callback(null, {forwardsChangesets: forwardsChangesets, callback(null, {forwardsChangesets: forwardsChangesets,
backwardsChangesets: backwardsChangesets, backwardsChangesets: backwardsChangesets,
apool: apool.toJsonable(), apool: apool.toJsonable(),
@ -396,7 +403,6 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
timeDeltas: timeDeltas, timeDeltas: timeDeltas,
start: startNum, start: startNum,
granularity: granularity }); granularity: granularity });
}
}); });
} }
@ -416,8 +422,9 @@ function getPadLines(padId, revNum, callback)
{ {
padManager.getPad(padId, function(err, _pad) padManager.getPad(padId, function(err, _pad)
{ {
if(ERR(err, callback)) return;
pad = _pad; pad = _pad;
callback(err); callback();
}); });
}, },
//get the atext //get the atext
@ -427,8 +434,9 @@ function getPadLines(padId, revNum, callback)
{ {
pad.getInternalRevisionAText(revNum, function(err, _atext) pad.getInternalRevisionAText(revNum, function(err, _atext)
{ {
if(ERR(err, callback)) return;
atext = _atext; atext = _atext;
callback(err); callback();
}); });
} }
else else
@ -445,7 +453,8 @@ function getPadLines(padId, revNum, callback)
} }
], function(err) ], function(err)
{ {
callback(err, result); if(ERR(err, callback)) return;
callback(null, result);
}); });
} }
@ -465,8 +474,9 @@ function composePadChangesets(padId, startNum, endNum, callback)
{ {
padManager.getPad(padId, function(err, _pad) padManager.getPad(padId, function(err, _pad)
{ {
if(ERR(err, callback)) return;
pad = _pad; pad = _pad;
callback(err); callback();
}); });
}, },
//fetch all changesets we need //fetch all changesets we need
@ -486,8 +496,9 @@ function composePadChangesets(padId, startNum, endNum, callback)
{ {
pad.getRevisionChangeset(revNum, function(err, value) pad.getRevisionChangeset(revNum, function(err, value)
{ {
if(ERR(err, callback)) return;
changesets[revNum] = value; changesets[revNum] = value;
callback(err); callback();
}); });
},callback); },callback);
}, },
@ -509,7 +520,7 @@ function composePadChangesets(padId, startNum, endNum, callback)
//return err and changeset //return err and changeset
function(err) function(err)
{ {
if(err) throw err; if(ERR(err, callback)) return;
callback(err, changeset); callback(null, changeset);
}); });
} }

View file

@ -20,6 +20,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var log4js = require('log4js'); var log4js = require('log4js');
var os = require("os"); var os = require("os");
var socketio = require('socket.io'); var socketio = require('socket.io');
@ -91,6 +92,9 @@ async.waterfall([
var httpLogger = log4js.getLogger("http"); var httpLogger = log4js.getLogger("http");
app.configure(function() app.configure(function()
{ {
// Activate http basic auth if it has been defined in settings.json
if(settings.httpAuth != null) app.use(basic_auth);
// If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158. // If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158.
// Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway. // Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway.
if (!(settings.loglevel === "WARN" || settings.loglevel == "ERROR")) if (!(settings.loglevel === "WARN" || settings.loglevel == "ERROR"))
@ -98,6 +102,12 @@ async.waterfall([
app.use(express.cookieParser()); app.use(express.cookieParser());
}); });
app.error(function(err, req, res, next){
res.send(500);
console.error(err.stack ? err.stack : err.toString());
gracefulShutdown();
});
//serve static files //serve static files
app.get('/static/*', function(req, res) app.get('/static/*', function(req, res)
{ {
@ -129,7 +139,7 @@ async.waterfall([
{ {
securityManager.checkAccess(req.params.pad, req.cookies.sessionid, req.cookies.token, req.cookies.password, function(err, accessObj) securityManager.checkAccess(req.params.pad, req.cookies.sessionid, req.cookies.token, req.cookies.password, function(err, accessObj)
{ {
if(err) throw err; if(ERR(err, callback)) return;
//there is access, continue //there is access, continue
if(accessObj.accessStatus == "grant") if(accessObj.accessStatus == "grant")
@ -144,6 +154,26 @@ async.waterfall([
}); });
} }
//checks for basic http auth
function basic_auth (req, res, next) {
if (req.headers.authorization && req.headers.authorization.search('Basic ') === 0) {
// fetch login and password
if (new Buffer(req.headers.authorization.split(' ')[1], 'base64').toString() == settings.httpAuth) {
next();
return;
}
}
res.header('WWW-Authenticate', 'Basic realm="Protected Area"');
if (req.headers.authorization) {
setTimeout(function () {
res.send('Authentication required', 401);
}, 1000);
} else {
res.send('Authentication required', 401);
}
}
//serve read only pad //serve read only pad
app.get('/ro/:id', function(req, res) app.get('/ro/:id', function(req, res)
{ {
@ -159,12 +189,14 @@ async.waterfall([
{ {
readOnlyManager.getPadId(req.params.id, function(err, _padId) readOnlyManager.getPadId(req.params.id, function(err, _padId)
{ {
if(ERR(err, callback)) return;
padId = _padId; padId = _padId;
//we need that to tell hasPadAcess about the pad //we need that to tell hasPadAcess about the pad
req.params.pad = padId; req.params.pad = padId;
callback(err); callback();
}); });
}, },
//render the html document //render the html document
@ -182,8 +214,9 @@ async.waterfall([
//render the html document //render the html document
exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html) exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
{ {
if(ERR(err, callback)) return;
html = _html; html = _html;
callback(err); callback();
}); });
}); });
} }
@ -191,7 +224,7 @@ async.waterfall([
{ {
//throw any unexpected error //throw any unexpected error
if(err && err != "notfound") if(err && err != "notfound")
throw err; ERR(err);
if(err == "notfound") if(err == "notfound")
res.send('404 - Not Found', 404); res.send('404 - Not Found', 404);

View file

@ -17,6 +17,7 @@
var async = require("async"); var async = require("async");
var Changeset = require("./Changeset"); var Changeset = require("./Changeset");
var padManager = require("../db/PadManager"); var padManager = require("../db/PadManager");
var ERR = require("async-stacktrace");
function getPadPlainText(pad, revNum) function getPadPlainText(pad, revNum)
{ {
@ -58,8 +59,9 @@ function getPadHTML(pad, revNum, callback)
{ {
pad.getInternalRevisionAText(revNum, function (err, revisionAtext) pad.getInternalRevisionAText(revNum, function (err, revisionAtext)
{ {
if(ERR(err, callback)) return;
atext = revisionAtext; atext = revisionAtext;
callback(err); callback();
}); });
} }
else else
@ -81,7 +83,8 @@ function getPadHTML(pad, revNum, callback)
function (err) function (err)
{ {
callback(err, html); if(ERR(err, callback)) return;
callback(null, html);
}); });
} }
@ -410,11 +413,7 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
{ {
padManager.getPad(padId, function (err, pad) padManager.getPad(padId, function (err, pad)
{ {
if (err) if(ERR(err, callback)) return;
{
callback(err);
return;
}
var head = (noDocType ? '' : '<!doctype html>\n') + '<html lang="en">\n' + (noDocType ? '' : '<head>\n' + '<meta charset="utf-8">\n' + '<style> * { font-family: arial, sans-serif;\n' + 'font-size: 13px;\n' + 'line-height: 17px; }</style>\n' + '</head>\n') + '<body>'; var head = (noDocType ? '' : '<!doctype html>\n') + '<html lang="en">\n' + (noDocType ? '' : '<head>\n' + '<meta charset="utf-8">\n' + '<style> * { font-family: arial, sans-serif;\n' + 'font-size: 13px;\n' + 'line-height: 17px; }</style>\n' + '</head>\n') + '<body>';
@ -422,7 +421,8 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
getPadHTML(pad, revNum, function (err, html) getPadHTML(pad, revNum, function (err, html)
{ {
callback(err, head + html + foot); if(ERR(err, callback)) return;
callback(null, head + html + foot);
}); });
}); });
} }

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
var jsdom = require('jsdom').jsdom; var jsdom = require('jsdom-nocontextifiy').jsdom;
var log4js = require('log4js'); var log4js = require('log4js');
var Changeset = require("./Changeset"); var Changeset = require("./Changeset");

View file

@ -19,6 +19,7 @@
* limitations under the License. * limitations under the License.
*/ */
var ERR = require("async-stacktrace");
var settings = require('./Settings'); var settings = require('./Settings');
var async = require('async'); var async = require('async');
var fs = require('fs'); var fs = require('fs');
@ -77,7 +78,7 @@ exports.minifyJS = function(req, res, jsFilename)
//read the files in the folder //read the files in the folder
fs.readdir(path, function(err, files) fs.readdir(path, function(err, files)
{ {
if(err) { callback(err); return; } if(ERR(err, callback)) return;
//we wanna check the directory itself for changes too //we wanna check the directory itself for changes too
files.push("."); files.push(".");
@ -88,7 +89,7 @@ exports.minifyJS = function(req, res, jsFilename)
//get the stat data of this file //get the stat data of this file
fs.stat(path + "/" + filename, function(err, stats) fs.stat(path + "/" + filename, function(err, stats)
{ {
if(err) { callback(err); return; } if(ERR(err, callback)) return;
//get the modification time //get the modification time
var modificationTime = stats.mtime.getTime(); var modificationTime = stats.mtime.getTime();
@ -110,7 +111,11 @@ exports.minifyJS = function(req, res, jsFilename)
//check the modification time of the minified js //check the modification time of the minified js
fs.stat("../var/minified_" + jsFilename, function(err, stats) fs.stat("../var/minified_" + jsFilename, function(err, stats)
{ {
if(err && err.code != "ENOENT") callback(err); if(err && err.code != "ENOENT")
{
ERR(err, callback);
return;
}
//there is no minfied file or there new changes since this file was generated, so continue generating this file //there is no minfied file or there new changes since this file was generated, so continue generating this file
if((err && err.code == "ENOENT") || stats.mtime.getTime() < latestModification) if((err && err.code == "ENOENT") || stats.mtime.getTime() < latestModification)
@ -131,8 +136,9 @@ exports.minifyJS = function(req, res, jsFilename)
{ {
fs.readFile("../static/js/" + item, "utf-8", function(err, data) fs.readFile("../static/js/" + item, "utf-8", function(err, data)
{ {
if(ERR(err, callback)) return;
fileValues[item] = data; fileValues[item] = data;
callback(err); callback();
}); });
}, callback); }, callback);
}, },
@ -161,6 +167,8 @@ exports.minifyJS = function(req, res, jsFilename)
//read the included file //read the included file
fs.readFile(filename, "utf-8", function(err, data) fs.readFile(filename, "utf-8", function(err, data)
{ {
if(ERR(err, callback)) return;
//compress the file //compress the file
if(type == "JS") if(type == "JS")
{ {
@ -188,17 +196,19 @@ exports.minifyJS = function(req, res, jsFilename)
embeds[item] = embeds[item].substr(0, embeds[item].length-1); embeds[item] = embeds[item].substr(0, embeds[item].length-1);
embeds[item] = "'" + embeds[item] + "'"; embeds[item] = "'" + embeds[item] + "'";
callback(err); callback();
}); });
}, function(err) }, function(err)
{ {
if(ERR(err, callback)) return;
//replace the include command with the include //replace the include command with the include
for(var i in embeds) for(var i in embeds)
{ {
fileValues["ace.js"]=fileValues["ace.js"].replace(i, embeds[i]); fileValues["ace.js"]=fileValues["ace.js"].replace(i, embeds[i]);
} }
callback(err); callback();
}); });
}, },
//put all together and write it into a file //put all together and write it into a file
@ -227,7 +237,10 @@ exports.minifyJS = function(req, res, jsFilename)
if(os.type().indexOf("Windows") == -1) if(os.type().indexOf("Windows") == -1)
{ {
gzip(result, 9, function(err, compressedResult){ gzip(result, 9, function(err, compressedResult){
if(err) {callback(err); return} //weird gzip bug that returns 0 instead of null if everything is ok
err = err === 0 ? null : err;
if(ERR(err, callback)) return;
fs.writeFile("../var/minified_" + jsFilename + ".gz", compressedResult, callback); fs.writeFile("../var/minified_" + jsFilename + ".gz", compressedResult, callback);
}); });
@ -242,7 +255,10 @@ exports.minifyJS = function(req, res, jsFilename)
} }
], function(err) ], function(err)
{ {
if(err && err != "stop") throw err; if(err && err != "stop")
{
if(ERR(err)) return;
}
//check if gzip is supported by this browser //check if gzip is supported by this browser
var gzipSupport = req.header('Accept-Encoding', '').indexOf('gzip') != -1; var gzipSupport = req.header('Accept-Encoding', '').indexOf('gzip') != -1;
@ -271,14 +287,15 @@ exports.minifyJS = function(req, res, jsFilename)
{ {
fs.readFile("../static/js/" + item, "utf-8", function(err, data) fs.readFile("../static/js/" + item, "utf-8", function(err, data)
{ {
if(ERR(err, callback)) return;
fileValues[item] = data; fileValues[item] = data;
callback(err); callback();
}); });
}, },
//send all files together //send all files together
function(err) function(err)
{ {
if(err) throw err; if(ERR(err)) return;
for(var i=0;i<jsFiles.length;i++) for(var i=0;i<jsFiles.length;i++)
{ {

View file

@ -68,6 +68,11 @@ exports.abiword = null;
*/ */
exports.loglevel = "INFO"; exports.loglevel = "INFO";
/**
* Http basic auth, with "user:password" format
*/
exports.httpAuth = null;
//read the settings sync //read the settings sync
var settingsStr = fs.readFileSync("../settings.json").toString(); var settingsStr = fs.readFileSync("../settings.json").toString();

View file

@ -20,7 +20,8 @@
"gzip" : "0.1.0", "gzip" : "0.1.0",
"formidable" : "1.0.7", "formidable" : "1.0.7",
"log4js" : "0.3.9", "log4js" : "0.3.9",
"jsdom" : "0.2.9" "jsdom-nocontextifiy" : "0.2.10",
"async-stacktrace" : "0.0.2"
}, },
"version" : "1.0.0" "version" : "1.0.0"
} }

View file

@ -43,6 +43,9 @@
Abiword is needed to enable the import/export of pads*/ Abiword is needed to enable the import/export of pads*/
"abiword" : null, "abiword" : null,
/* This setting is used if you need http basic auth */
// "httpAuth" : "user:pass",
/* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ /* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */
"loglevel": "INFO" "loglevel": "INFO"
} }

View file

@ -32,6 +32,23 @@ ul.list-bullet6 { list-style-type: square; }
ul.list-bullet7 { list-style-type: disc; } ul.list-bullet7 { list-style-type: disc; }
ul.list-bullet8 { list-style-type: circle; } ul.list-bullet8 { list-style-type: circle; }
ul.list-indent1 { margin-left: 1.5em; }
ul.list-indent2 { margin-left: 3em; }
ul.list-indent3 { margin-left: 4.5em; }
ul.list-indent4 { margin-left: 6em; }
ul.list-indent5 { margin-left: 7.5em; }
ul.list-indent6 { margin-left: 9em; }
ul.list-indent7 { margin-left: 10.5em; }
ul.list-indent8 { margin-left: 12em; }
ul.list-indent1 { list-style-type: none; }
ul.list-indent2 { list-style-type: none; }
ul.list-indent3 { list-style-type: none; }
ul.list-indent4 { list-style-type: none; }
ul.list-indent5 { list-style-type: none; }
ul.list-indent6 { list-style-type: none; }
ul.list-indent7 { list-style-type: none; }
ul.list-indent8 { list-style-type: none; }
body { body {
margin: 0; margin: 0;

View file

@ -472,12 +472,10 @@ table#otheruserstable { display: none; }
background: url(../../static/img/connectingbar.gif) no-repeat center 60px; background: url(../../static/img/connectingbar.gif) no-repeat center 60px;
height: 100px; height: 100px;
} }
.modaldialog.cboxreconnecting { .modaldialog.cboxreconnecting,
background: #fed;
}
.modaldialog.cboxconnecting, .modaldialog.cboxconnecting,
.modaldialog.cboxdisconnected { .modaldialog.cboxdisconnected {
background: #fdd; background: #8FCDE0;
} }
.cboxdisconnected #connectionboxinner div { display: none; } .cboxdisconnected #connectionboxinner div { display: none; }
.cboxdisconnected_userdup #connectionboxinner #disconnected_userdup { display: block; } .cboxdisconnected_userdup #connectionboxinner #disconnected_userdup { display: block; }
@ -1146,17 +1144,106 @@ width:33px !important;
color: #999; color: #999;
} }
label[for=readonlyinput] {
margin: 0 10px 0 2px;
}
#qr_center {
margin: 10px 10px auto 0;
text-align: center;
}
#qrcode{
margin-left:10px;
}
@media screen and (max-width: 960px) {
.modaldialog {
position: relative;
margin: 0 auto;
width: 80%;
top: 40px;
left: 0;
}
}
@media screen and (max-width: 600px) { @media screen and (max-width: 600px) {
#editbar ul li { #editbar ul li {
padding: 4px 1px; padding: 4px 1px;
} }
} }
#embedreadonlyqr{ @media only screen and (min-device-width: 320px) and (max-device-width: 600px) {
padding-top:20px; #editbar ul li {
margin-left:100px; padding: 4px 3px;
}
#editbar ul#menu_right > li {
padding: 4px 8px;
margin-top: 2px;
}
#chaticon {
opacity: .8;
}
#users {
right: none;
left: 30px;
}
#mycolorpicker {
right: 0;
left: 0 !important;
}
#editorcontainer {
margin-bottom: 33px;
}
#editbar ul#menu_right {
background: #f7f7f7;
background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%);
background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%);
background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%);
background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%);
width: 100%;
overflow: hidden;
height: 32px;
position: fixed;
bottom: 0;
border-top: 1px solid #ccc;
}
#editbar ul#menu_right li:not(:last-child) {
display: none;
}
#editbar ul#menu_right li:last-child {
height: 24px;
border-radius: 0;
margin-top: 0;
border: 0;
float: right;
}
#chaticon {
bottom: 0;
right: 55px;
border-right: none;
border-radius: 0;
background: #f7f7f7;
background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%);
background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%);
background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%);
background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%);
border: 0;
}
#chatbox {
bottom: 32px;
right: 0;
border-top-right-radius: 0;
}
#editbar ul li a span {
top: -3px;
}
#usericonback {
margin-top: 4px;
}
#sidediv {
display:none;
} }
#qrcode{
margin-left:10px;
} }

View file

@ -1,6 +1,8 @@
<!doctype html> <!doctype html>
<html> <html>
<title>RPG Write</title> <title>RPG Write</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<style> <style>
*{ margin:0;padding:0; } *{ margin:0;padding:0; }
body { body {
@ -13,13 +15,12 @@
background: -ms-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; background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
overflow-x: hidden; overflow-x: hidden;
border-top: 8px solid rgba(51,51,51,.8) border-top: 8px solid rgba(51,51,51,.8);
} }
#container { #container {
text-shadow: 0 1px 1px #fff; text-shadow: 0 1px 1px #fff;
border-top: 1px solid #999; border-top: 1px solid #999;
margin-top: 160px; margin-top: 160px;
width: 100%;
text-align: center; text-align: center;
padding: 15px; padding: 15px;
background: #eee; background: #eee;
@ -28,7 +29,7 @@
background: -ms-linear-gradient(#fff,#ccc); background: -ms-linear-gradient(#fff,#ccc);
background: -o-linear-gradient(#fff,#ccc); background: -o-linear-gradient(#fff,#ccc);
opacity: .9; opacity: .9;
box-shadow: 0px 1px 8px rgba(0,0,0,0.3) box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
} }
#button { #button {
margin: 0 auto; margin: 0 auto;
@ -45,7 +46,7 @@
background: -moz-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737); background: -moz-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
background: -ms-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737); background: -ms-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
background: -o-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737); background: -o-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
box-shadow: inset 0 1px 3px rgba(0,0,0,0.9) box-shadow: inset 0 1px 3px rgba(0,0,0,0.9);
} }
#button:hover { #button:hover {
cursor: pointer; cursor: pointer;
@ -53,21 +54,21 @@
background: -webkit-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747); background: -webkit-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
background: -moz-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747); background: -moz-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
background: -ms-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747); background: -ms-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
background: -o-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747) background: -o-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
} }
#button:active { #button:active {
box-shadow: inset 0 1px 12px rgba(0,0,0,0.9); box-shadow: inset 0 1px 12px rgba(0,0,0,0.9);
background: #444 background: #444;
} }
#label { #label {
text-align: left; text-align: left;
margin: 0 auto; margin: 0 auto;
width: 300px width: 300px;
} }
input { input {
vertical-align: middle; vertical-align: middle;
font-weight: bold; font-weight: bold;
font-size: 15px font-size: 15px;
} }
input[type="text"] { input[type="text"] {
width: 243px; width: 243px;
@ -76,23 +77,43 @@
border: 1px solid #bbb; border: 1px solid #bbb;
outline: none; outline: none;
border-radius: 3px; border-radius: 3px;
text-shadow: 0 0 1px #fff text-shadow: 0 0 1px #fff;
} }
input[type="submit"] { input[type="submit"] {
width: 45px; width: 45px;
margin-left: -50px; margin-left: -50px;
padding: 8px padding: 8px;
} }
input[type="submit"]::-moz-focus-inner { border: 0 } input[type="submit"]::-moz-focus-inner { border: 0 }
@-moz-document url-prefix() { input[type="submit"] { padding: 7px } } @-moz-document url-prefix() { input[type="submit"] { padding: 7px } }
@media only screen and (min-device-width: 320px) and (max-device-width: 600px) {
body {
background: #bbb;
background: -webkit-linear-gradient(#aaa,#eee 60%) center fixed;
height: 100%;
}
#container {
margin-top: 0;
text-align: left;
}
#button, #label {
text-align: center;
width: 95%;
}
form {
text-align: center;
}
input[type=text] {
width: 75%;
}
}
</style> </style>
<body onload="document.mainform.padname.focus();">
<link href="static/custom/index.css" rel="stylesheet"> <link href="static/custom/index.css" rel="stylesheet">
<script src="static/custom/index.js"></script> <script src="static/custom/index.js"></script>
<div id="container"> <div id="container">
<div id="button" onclick="go2Random()">New Pad</div><br><div id="label">or create/open a Pad with the name</div> <div id="button" onclick="go2Random()" class="translate">New Pad</div><br><div id="label" class="translate">or create/open a Pad with the name</div>
<form action="#" name="mainform" onsubmit="go2Name();return false;"> <form action="#" onsubmit="go2Name();return false;">
<input type="text" name="padname" id="padname" autofocus> <input type="text" id="padname" autofocus>
<input type="submit" value="OK"> <input type="submit" value="OK">
</form> </form>
</div> </div>
@ -126,3 +147,4 @@
</script> </script>
</body> </body>
</html> </html>
</html>

View file

@ -76,10 +76,13 @@ function isArray(testObject)
if (typeof exports !== "undefined") if (typeof exports !== "undefined")
{ {
var navigator = {userAgent: "node-js"}; userAgent = "node-js";
}
else
{
userAgent = navigator.userAgent.toLowerCase();
} }
// Figure out what browser is being used (stolen from jquery 1.2.1) // Figure out what browser is being used (stolen from jquery 1.2.1)
userAgent = navigator.userAgent.toLowerCase();
var browser = { var browser = {
version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1], version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
safari: /webkit/.test(userAgent), safari: /webkit/.test(userAgent),

View file

@ -3534,7 +3534,8 @@ function OUTER(gscope)
function doIndentOutdent(isOut) function doIndentOutdent(isOut)
{ {
if (!(rep.selStart && rep.selEnd)) if (!(rep.selStart && rep.selEnd) ||
((rep.selStart[0] == rep.selEnd[0]) && (rep.selStart[1] == rep.selEnd[1]) && rep.selEnd[1] > 1))
{ {
return false; return false;
} }
@ -3544,24 +3545,24 @@ function OUTER(gscope)
lastLine = Math.max(firstLine, rep.selEnd[0] - ((rep.selEnd[1] == 0) ? 1 : 0)); lastLine = Math.max(firstLine, rep.selEnd[0] - ((rep.selEnd[1] == 0) ? 1 : 0));
var mods = []; var mods = [];
var foundLists = false;
for (var n = firstLine; n <= lastLine; n++) for (var n = firstLine; n <= lastLine; n++)
{ {
var listType = getLineListType(n); var listType = getLineListType(n);
var t = 'indent';
var level = 0;
if (listType) if (listType)
{ {
listType = /([a-z]+)([12345678])/.exec(listType); listType = /([a-z]+)([12345678])/.exec(listType);
if (listType) if (listType)
{ {
foundLists = true; t = listType[1];
var t = listType[1]; level = Number(listType[2]);
var level = Number(listType[2]); }
var newLevel = Math.max(1, Math.min(MAX_LIST_LEVEL, level + (isOut ? -1 : 1))); }
var newLevel = Math.max(0, Math.min(MAX_LIST_LEVEL, level + (isOut ? -1 : 1)));
if (level != newLevel) if (level != newLevel)
{ {
mods.push([n, t + newLevel]); mods.push([n, (newLevel > 0) ? t + newLevel : '']);
}
}
} }
} }
@ -3570,7 +3571,7 @@ function OUTER(gscope)
setLineListTypes(mods); setLineListTypes(mods);
} }
return foundLists; return true;
} }
editorInfo.ace_doIndentOutdent = doIndentOutdent; editorInfo.ace_doIndentOutdent = doIndentOutdent;
@ -5231,7 +5232,8 @@ function OUTER(gscope)
var allLinesAreList = true; var allLinesAreList = true;
for (var n = firstLine; n <= lastLine; n++) for (var n = firstLine; n <= lastLine; n++)
{ {
if (!getLineListType(n)) var listType = getLineListType(n);
if (!listType || listType.slice(0, 'bullet'.length) != 'bullet')
{ {
allLinesAreList = false; allLinesAreList = false;
break; break;
@ -5241,8 +5243,16 @@ function OUTER(gscope)
var mods = []; var mods = [];
for (var n = firstLine; n <= lastLine; n++) for (var n = firstLine; n <= lastLine; n++)
{ {
var t = '';
var level = 0;
var listType = /([a-z]+)([12345678])/.exec(getLineListType(n));
if (listType)
{
t = listType[1];
level = Number(listType[2]);
}
var t = getLineListType(n); var t = getLineListType(n);
mods.push([n, allLinesAreList ? '' : (t ? t : 'bullet1')]); mods.push([n, allLinesAreList ? 'indent' + level : (t ? 'bullet' + level : 'bullet1')]);
} }
setLineListTypes(mods); setLineListTypes(mods);
} }
@ -5647,31 +5657,17 @@ function OUTER(gscope)
{ {
var newNumLines = rep.lines.length(); var newNumLines = rep.lines.length();
if (newNumLines < 1) newNumLines = 1; if (newNumLines < 1) newNumLines = 1;
if (newNumLines != lineNumbersShown) //update height of all current line numbers
{
var container = sideDivInner;
var odoc = outerWin.document;
while (lineNumbersShown < newNumLines)
{
lineNumbersShown++;
var n = lineNumbersShown;
var div = odoc.createElement("DIV");
div.appendChild(odoc.createTextNode(String(n)));
container.appendChild(div);
}
while (lineNumbersShown > newNumLines)
{
container.removeChild(container.lastChild);
lineNumbersShown--;
}
}
if (currentCallStack && currentCallStack.domClean) if (currentCallStack && currentCallStack.domClean)
{ {
var a = sideDivInner.firstChild; var a = sideDivInner.firstChild;
var b = doc.body.firstChild; var b = doc.body.firstChild;
var n = 0;
while (a && b) while (a && b)
{ {
if(n > lineNumbersShown) //all updated, break
break;
var h = (b.clientHeight || b.offsetHeight); var h = (b.clientHeight || b.offsetHeight);
if (b.nextSibling) if (b.nextSibling)
{ {
@ -5685,10 +5681,42 @@ function OUTER(gscope)
if (h) if (h)
{ {
var hpx = h + "px"; var hpx = h + "px";
if (a.style.height != hpx) a.style.height = hpx; if (a.style.height != hpx) {
a.style.height = hpx;
}
} }
a = a.nextSibling; a = a.nextSibling;
b = b.nextSibling; b = b.nextSibling;
n++;
}
}
if (newNumLines != lineNumbersShown)
{
var container = sideDivInner;
var odoc = outerWin.document;
var fragment = odoc.createDocumentFragment();
while (lineNumbersShown < newNumLines)
{
lineNumbersShown++;
var n = lineNumbersShown;
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)
{
container.removeChild(container.lastChild);
lineNumbersShown--;
} }
} }
} }

View file

@ -16,6 +16,10 @@
var chat = (function() var chat = (function()
{ {
var ua = navigator.userAgent.toLowerCase();
var isAndroid = ua.indexOf("android") > -1;
var isMobileSafari = ua.indexOf("mobile") > -1;
var bottomMargin = "0px";
var chatMentions = 0; var chatMentions = 0;
var title = document.title; var title = document.title;
var self = { var self = {
@ -31,6 +35,8 @@ var chat = (function()
$("#chatbox").resizable( $("#chatbox").resizable(
{ {
handles: 'nw', handles: 'nw',
minHeight: 40,
minWidth: 80,
start: function (event, ui) start: function (event, ui)
{ {
$("#focusprotector").show(); $("#focusprotector").show();
@ -39,7 +45,10 @@ var chat = (function()
{ {
$("#focusprotector").hide(); $("#focusprotector").hide();
$("#chatbox").css({right: "20px", bottom: "0px", left: "", top: ""}); if(isAndroid || isMobileSafari)
bottommargin = "32px";
$("#chatbox").css({right: "20px", bottom: bottomMargin, left: "", top: ""});
self.scrollDown(); self.scrollDown();
} }
@ -51,10 +60,14 @@ var chat = (function()
hide: function () hide: function ()
{ {
$("#chatcounter").text("0"); $("#chatcounter").text("0");
$("#chatbox").hide("slide", { direction: "down" }, 750, function() if(isAndroid || isMobileSafari) {
$("#chatbox").toggle();
}
else
{ {
$("#chaticon").show("slide", { direction: "down" }, 500); $("#chatbox").toggle("slide", { direction: "down" }, 625);
}); }
}, },
scrollDown: function() scrollDown: function()
{ {

View file

@ -473,7 +473,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
if (tname == "ul") if (tname == "ul")
{ {
var type; var type;
var rr = cls && /(?:^| )list-(bullet[12345678])\b/.exec(cls); var rr = cls && /(?:^| )list-([a-z]+[12345678])\b/.exec(cls);
type = rr && rr[1] || "bullet" + String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1)); type = rr && rr[1] || "bullet" + String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1));
oldListTypeOrNull = (_enterList(state, type) || 'none'); oldListTypeOrNull = (_enterList(state, type) || 'none');
} }

View file

@ -21,6 +21,7 @@ var LineNumbersDisabled = false;
var noColors = false; var noColors = false;
var useMonospaceFontGlobal = false; var useMonospaceFontGlobal = false;
var globalUserName = false; var globalUserName = false;
var hideQRCode = false;
$(document).ready(function() $(document).ready(function()
{ {
@ -86,12 +87,14 @@ function getParams()
var showLineNumbers = params["showLineNumbers"]; var showLineNumbers = params["showLineNumbers"];
var useMonospaceFont = params["useMonospaceFont"]; var useMonospaceFont = params["useMonospaceFont"];
var IsnoColors = params["noColors"]; var IsnoColors = params["noColors"];
var hideQRCode = params["hideQRCode"];
if(IsnoColors) if(IsnoColors)
{ {
if(IsnoColors == "true") if(IsnoColors == "true")
{ {
noColors = true; noColors = true;
$('#clearAuthorship').hide();
} }
} }
if(showControls) if(showControls)
@ -102,7 +105,6 @@ function getParams()
$('#editorcontainer').css({"top":"0px"}); $('#editorcontainer').css({"top":"0px"});
} }
} }
if(showChat) if(showChat)
{ {
if(showChat == "false") if(showChat == "false")
@ -110,7 +112,6 @@ function getParams()
$('#chaticon').hide(); $('#chaticon').hide();
} }
} }
if(showLineNumbers) if(showLineNumbers)
{ {
if(showLineNumbers == "false") if(showLineNumbers == "false")
@ -118,7 +119,6 @@ function getParams()
LineNumbersDisabled = true; LineNumbersDisabled = true;
} }
} }
if(useMonospaceFont) if(useMonospaceFont)
{ {
if(useMonospaceFont == "true") if(useMonospaceFont == "true")
@ -126,13 +126,15 @@ function getParams()
useMonospaceFontGlobal = true; useMonospaceFontGlobal = true;
} }
} }
if(userName) if(userName)
{ {
// If the username is set as a parameter we should set a global value that we can call once we have initiated the pad. // If the username is set as a parameter we should set a global value that we can call once we have initiated the pad.
globalUserName = unescape(userName); globalUserName = unescape(userName);
} }
if(hideQRCode)
{
$('#qrcode').hide();
}
} }
function getUrlVars() function getUrlVars()
@ -174,7 +176,7 @@ function handshake()
function sendClientReady(isReconnect) function sendClientReady(isReconnect)
{ {
var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1); var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1);
padId = unescape(padId); // unescape neccesary due to Safari and Opera interpretation of spaces padId = decodeURIComponent(padId); // unescape neccesary due to Safari and Opera interpretation of spaces
if(!isReconnect) if(!isReconnect)
document.title = document.title + " | " + padId; document.title = document.title + " | " + padId;

View file

@ -206,15 +206,14 @@ var padeditbar = (function()
{ {
if ($('#readonlyinput').is(':checked')) if ($('#readonlyinput').is(':checked'))
{ {
$('#qrcode').show();
var basePath = document.location.href.substring(0, document.location.href.indexOf("/p/")); var basePath = document.location.href.substring(0, document.location.href.indexOf("/p/"));
var readonlyLink = basePath + "/ro/" + clientVars.readOnlyId; var readonlyLink = basePath + "/ro/" + clientVars.readOnlyId;
$('#embedinput').val("<iframe src='" + readonlyLink + "?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false' width=600 height=400>"); $('#embedinput').val("<iframe src='" + readonlyLink + "?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false' width=600 height=400>");
$('#linkinput').val(readonlyLink); $('#linkinput').val(readonlyLink);
$('#embedreadonlyqr').attr("src","https://chart.googleapis.com/chart?chs=200x200&cht=qr&chld=H|0&chl=" + readonlyLink);
} }
else else
{ {
$('#qrcode').hide();
var padurl = window.location.href.split("?")[0]; var padurl = window.location.href.split("?")[0];
$('#embedinput').val("<iframe src='" + padurl + "?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false' width=600 height=400>"); $('#embedinput').val("<iframe src='" + padurl + "?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false' width=600 height=400>");
$('#linkinput').val(padurl); $('#linkinput').val(padurl);

View file

@ -711,8 +711,15 @@ var paduserlist = (function()
} }
$("#myswatch").css({'background-color': myUserInfo.colorId}); $("#myswatch").css({'background-color': myUserInfo.colorId});
if ($.browser.msie && parseInt($.browser.version) <= 8) {
$("#usericon").css({'box-shadow': 'inset 0 0 30px ' + myUserInfo.colorId,'background-color': myUserInfo.colorId});
}
else
{
$("#usericon").css({'box-shadow': 'inset 0 0 30px ' + myUserInfo.colorId}); $("#usericon").css({'box-shadow': 'inset 0 0 30px ' + myUserInfo.colorId});
} }
}
}; };
return self; return self;
}()); }());

View file

@ -4,6 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="robots" content="noindex, nofollow"> <meta name="robots" content="noindex, nofollow">
<title>RPG Write</title> <title>RPG Write</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<!-- CSS --> <!-- CSS -->
<link href="../static/css/pad.css" rel="stylesheet"> <link href="../static/css/pad.css" rel="stylesheet">
<!-- javascript --> <!-- javascript -->
@ -50,12 +51,12 @@
</a> </a>
</li> </li>
<li onClick="window.pad&&pad.editbarClick('indent');return false;" > <li onClick="window.pad&&pad.editbarClick('indent');return false;" >
<a title="Indent List"> <a title="Indent">
<div class="buttonicon" style="background-position:0px -52px"></div> <div class="buttonicon" style="background-position:0px -52px"></div>
</a> </a>
</li> </li>
<li onClick="window.pad&&pad.editbarClick('outdent');return false;" > <li onClick="window.pad&&pad.editbarClick('outdent');return false;" >
<a title="Unindent List"> <a title="Unindent">
<div class="buttonicon" style="background-position:0px -134px"></div> <div class="buttonicon" style="background-position:0px -134px"></div>
</a> </a>
</li> </li>
@ -71,7 +72,7 @@
</a> </a>
</li> </li>
<li class="separator"></li> <li class="separator"></li>
<li onClick="window.pad&&pad.editbarClick('clearauthorship');return false;" > <li id="clearAuthorship" onClick="window.pad&&pad.editbarClick('clearauthorship');return false;" >
<a title="Clear Authorship Colors"> <a title="Clear Authorship Colors">
<div class="buttonicon" style="background-position:0px -86px"></div> <div class="buttonicon" style="background-position:0px -86px"></div>
</a> </a>
@ -86,7 +87,7 @@
</a> </a>
</li> </li>
<li onClick="window.pad&&pad.editbarClick('embed');return false;" > <li onClick="window.pad&&pad.editbarClick('embed');return false;" >
<a id="embedlink" title="Embed this pad"> <a id="embedlink" title="Share and Embed this pad">
<div class="buttonicon" style="background-position:0px -18px"></div> <div class="buttonicon" style="background-position:0px -18px"></div>
</a> </a>
</li> </li>
@ -225,7 +226,7 @@
</div><br/> </div><br/>
<div id="qrcode"> <div id="qrcode">
<label for="embedreadonlyqr">QR code:</label><br/> <label for="embedreadonlyqr">QR code:</label><br/>
<img id="embedreadonlyqr"> <div id="qr_center"><img id="embedreadonlyqr"></div>
</div> </div>
</div> </div>

View file

@ -62,7 +62,7 @@
//get the padId out of the url //get the padId out of the url
var urlParts= document.location.pathname.split("/"); var urlParts= document.location.pathname.split("/");
padId = urlParts[urlParts.length-2]; padId = decodeURIComponent(urlParts[urlParts.length-2]);
//set the title //set the title
document.title = document.title + " | " + padId; document.title = document.title + " | " + padId;
@ -271,7 +271,11 @@
<!-- termporary place holder--> <!-- termporary place holder-->
<a id = "returnbutton">Return to pad</a> <a id = "returnbutton">Return to pad</a>
<script> <script>
if(document.referrer.length > 0 && document.referrer.substring(document.referrer.lastIndexOf("/")-1,document.referrer.lastIndexOf("/")) === "p") {
$("#returnbutton").attr("href", document.referrer); $("#returnbutton").attr("href", document.referrer);
} else {
$("#returnbutton").attr("href", document.location.href.substring(0,document.location.href.lastIndexOf("/")));
}
</script> </script>
</div> </div>