mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-05-08 08:01:02 -04:00
merge with upstream. Fixed confict in pad.html
This commit is contained in:
parent
3248ca4cbb
commit
254046454d
91 changed files with 1674 additions and 1363 deletions
|
@ -71,7 +71,7 @@ Here is the **[FAQ](https://github.com/Pita/etherpad-lite/wiki/FAQ)**
|
|||
|
||||
**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> </li>
|
||||
<li>Install the dependencies with <code>bin/installDeps.sh</code><br> </li>
|
||||
<li>Start it with <code>bin/run.sh</code><br> </li>
|
||||
|
@ -114,8 +114,8 @@ You also help the project, if you only host a Etherpad Lite instance and share y
|
|||
# Modules created for this project
|
||||
|
||||
* [ueberDB](https://github.com/Pita/ueberDB) "transforms every database into a object key value store" - manages all database access
|
||||
* [doc.md](https://github.com/Pita/doc.md) "A simple JSDoc 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
|
||||
* [async-stacktrace](https://github.com/Pita/async-stacktrace) "Improves node.js stacktraces and makes it easier to handle errors"
|
||||
|
||||
# License
|
||||
[Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
NODE_VERSION="0.6.1"
|
||||
NODE_VERSION="0.6.5"
|
||||
|
||||
#Move to the folder where ep-lite is installed
|
||||
cd `dirname $0`
|
||||
|
|
133
bin/checkPad.js
Normal file
133
bin/checkPad.js
Normal 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);
|
||||
}
|
||||
});
|
|
@ -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
|
|
@ -16,7 +16,7 @@ hash curl > /dev/null 2>&1 || {
|
|||
|
||||
#Is node installed?
|
||||
hash node > /dev/null 2>&1 || {
|
||||
echo "Please install node.js ( http://nodesjs.org )" >&2
|
||||
echo "Please install node.js ( http://nodejs.org )" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,8 @@ hash npm > /dev/null 2>&1 || {
|
|||
|
||||
#check npm version
|
||||
NPM_VERSION=$(npm --version)
|
||||
if [ ! $(echo $NPM_VERSION | cut -d "." -f 1-2) = "1.0" ]; then
|
||||
echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.0.x" >&2
|
||||
if [ ! $(echo $NPM_VERSION | cut -d "." -f 1) = "1" ]; then
|
||||
echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.x" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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*
|
||||
|
|
@ -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*
|
||||
|
|
@ -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*
|
||||
|
|
@ -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
|
||||
|
|
@ -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*
|
||||
|
|
@ -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*
|
||||
|
|
@ -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*
|
||||
|
|
@ -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*
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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*
|
||||
|
|
@ -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 ()
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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*
|
||||
|
|
@ -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*
|
||||
|
|
@ -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
|
||||
|
150
node/db/API.js
150
node/db/API.js
|
@ -18,6 +18,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var customError = require("../utils/customError");
|
||||
var padManager = require("./PadManager");
|
||||
var padMessageHandler = require("../handler/PadMessageHandler");
|
||||
var readOnlyManager = require("./ReadOnlyManager");
|
||||
|
@ -87,7 +89,7 @@ exports.getText = function(padID, rev, callback)
|
|||
}
|
||||
else
|
||||
{
|
||||
callback({stop: "rev is not a number"});
|
||||
callback(new customError("rev is not a number", "apierror"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -95,25 +97,21 @@ exports.getText = function(padID, rev, callback)
|
|||
//ensure this is not a negativ number
|
||||
if(rev !== undefined && rev < 0)
|
||||
{
|
||||
callback({stop: "rev is a negativ number"});
|
||||
callback(new customError("rev is a negativ number","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//ensure this is not a float value
|
||||
if(rev !== undefined && !is_int(rev))
|
||||
{
|
||||
callback({stop: "rev is a float value"});
|
||||
callback(new customError("rev is a float value","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//get the pad
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//the client asked for a special revision
|
||||
if(rev !== undefined)
|
||||
|
@ -121,19 +119,18 @@ exports.getText = function(padID, rev, callback)
|
|||
//check if this is a valid revision
|
||||
if(rev > pad.getHeadRevisionNumber())
|
||||
{
|
||||
callback({stop: "rev is higher than the head revision of the pad"});
|
||||
callback(new customError("rev is higher than the head revision of the pad","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//get the text of this revision
|
||||
pad.getInternalRevisionAText(rev, function(err, atext)
|
||||
{
|
||||
if(!err)
|
||||
{
|
||||
data = {text: atext.text};
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
callback(err, data);
|
||||
data = {text: atext.text};
|
||||
|
||||
callback(null, data);
|
||||
})
|
||||
}
|
||||
//the client wants the latest text, lets return it to him
|
||||
|
@ -158,11 +155,7 @@ exports.setText = function(padID, text, callback)
|
|||
//get the pad
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//set the text
|
||||
pad.setText(text);
|
||||
|
@ -196,30 +189,26 @@ exports.getHTML = function(padID, rev, callback)
|
|||
}
|
||||
else
|
||||
{
|
||||
callback({stop: "rev is not a number"});
|
||||
callback(new customError("rev is not a number","apierror"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(rev !== undefined && rev < 0)
|
||||
{
|
||||
callback({stop: "rev is a negative number"});
|
||||
callback(new customError("rev is a negative number","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(rev !== undefined && !is_int(rev))
|
||||
{
|
||||
callback({stop: "rev is a float value"});
|
||||
callback(new customError("rev is a float value","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//the client asked for a special revision
|
||||
if(rev !== undefined)
|
||||
|
@ -227,18 +216,16 @@ exports.getHTML = function(padID, rev, callback)
|
|||
//check if this is a valid revision
|
||||
if(rev > pad.getHeadRevisionNumber())
|
||||
{
|
||||
callback({stop: "rev is higher than the head revision of the pad"});
|
||||
callback(new customError("rev is higher than the head revision of the pad","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//get the html of this revision
|
||||
exportHtml.getPadHTML(pad, rev, function(err, html)
|
||||
{
|
||||
if(!err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
data = {html: html};
|
||||
}
|
||||
callback(err, data);
|
||||
callback(null, data);
|
||||
});
|
||||
}
|
||||
//the client wants the latest text, lets return it to him
|
||||
|
@ -246,11 +233,11 @@ exports.getHTML = function(padID, rev, callback)
|
|||
{
|
||||
exportHtml.getPadHTML(pad, undefined, function (err, html)
|
||||
{
|
||||
if(!err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
data = {html: html};
|
||||
}
|
||||
callback(err, data);
|
||||
|
||||
callback(null, data);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -261,11 +248,7 @@ exports.setHTML = function(padID, html, callback)
|
|||
//get the pad
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
// add a new changeset with the new html to the pad
|
||||
importHtml.setPadHTML(pad, cleanText(html));
|
||||
|
@ -293,11 +276,7 @@ exports.getRevisionsCount = function(padID, callback)
|
|||
//get the pad
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
callback(null, {revisions: pad.getHeadRevisionNumber()});
|
||||
});
|
||||
|
@ -314,16 +293,17 @@ Example returns:
|
|||
exports.createPad = function(padID, text, callback)
|
||||
{
|
||||
//ensure there is no $ in the padID
|
||||
if(padID.indexOf("$") != -1)
|
||||
if(padID && padID.indexOf("$") != -1)
|
||||
{
|
||||
callback({stop: "createPad can't create group pads"});
|
||||
callback(new customError("createPad can't create group pads","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//create pad
|
||||
getPadSafe(padID, false, text, function(err)
|
||||
{
|
||||
callback(err);
|
||||
if(ERR(err, callback)) return;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -339,11 +319,7 @@ exports.deletePad = function(padID, callback)
|
|||
{
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
pad.remove(callback);
|
||||
});
|
||||
|
@ -362,16 +338,13 @@ exports.getReadOnlyID = function(padID, callback)
|
|||
//we don't need the pad object, but this function does all the security stuff for us
|
||||
getPadSafe(padID, true, function(err)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//get the readonlyId
|
||||
readOnlyManager.getReadOnlyId(padID, function(err, readOnlyId)
|
||||
{
|
||||
callback(err, {readOnlyID: readOnlyId});
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, {readOnlyID: readOnlyId});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -387,20 +360,16 @@ Example returns:
|
|||
exports.setPublicStatus = function(padID, publicStatus, callback)
|
||||
{
|
||||
//ensure this is a group pad
|
||||
if(padID.indexOf("$") == -1)
|
||||
if(padID && padID.indexOf("$") == -1)
|
||||
{
|
||||
callback({stop: "You can only get/set the publicStatus of pads that belong to a group"});
|
||||
callback(new customError("You can only get/set the publicStatus of pads that belong to a group","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//get the pad
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//convert string to boolean
|
||||
if(typeof publicStatus == "string")
|
||||
|
@ -424,20 +393,16 @@ Example returns:
|
|||
exports.getPublicStatus = function(padID, callback)
|
||||
{
|
||||
//ensure this is a group pad
|
||||
if(padID.indexOf("$") == -1)
|
||||
if(padID && padID.indexOf("$") == -1)
|
||||
{
|
||||
callback({stop: "You can only get/set the publicStatus of pads that belong to a group"});
|
||||
callback(new customError("You can only get/set the publicStatus of pads that belong to a group","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//get the pad
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
callback(null, {publicStatus: pad.getPublicStatus()});
|
||||
});
|
||||
|
@ -454,20 +419,16 @@ Example returns:
|
|||
exports.setPassword = function(padID, password, callback)
|
||||
{
|
||||
//ensure this is a group pad
|
||||
if(padID.indexOf("$") == -1)
|
||||
if(padID && padID.indexOf("$") == -1)
|
||||
{
|
||||
callback({stop: "You can only get/set the password of pads that belong to a group"});
|
||||
callback(new customError("You can only get/set the password of pads that belong to a group","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//get the pad
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//set the password
|
||||
pad.setPassword(password);
|
||||
|
@ -487,20 +448,16 @@ Example returns:
|
|||
exports.isPasswordProtected = function(padID, callback)
|
||||
{
|
||||
//ensure this is a group pad
|
||||
if(padID.indexOf("$") == -1)
|
||||
if(padID && padID.indexOf("$") == -1)
|
||||
{
|
||||
callback({stop: "You can only get/set the password of pads that belong to a group"});
|
||||
callback(new customError("You can only get/set the password of pads that belong to a group","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//get the pad
|
||||
getPadSafe(padID, true, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
callback(null, {isPasswordProtected: pad.isPasswordProtected()});
|
||||
});
|
||||
|
@ -528,34 +485,31 @@ function getPadSafe(padID, shouldExist, text, callback)
|
|||
//check if padID is a string
|
||||
if(typeof padID != "string")
|
||||
{
|
||||
callback({stop: "padID is not a string"});
|
||||
callback(new customError("padID is not a string","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//check if the padID maches the requirements
|
||||
if(!padManager.isValidPadId(padID))
|
||||
{
|
||||
callback({stop: "padID did not match requirements"});
|
||||
callback(new customError("padID did not match requirements","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//check if the pad exists
|
||||
padManager.doesPadExists(padID, function(err, exists)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//does not exist, but should
|
||||
else if(exists == false && shouldExist == true)
|
||||
if(exists == false && shouldExist == true)
|
||||
{
|
||||
callback({stop: "padID does not exist"});
|
||||
callback(new customError("padID does not exist","apierror"));
|
||||
}
|
||||
//does exists, but shouldn't
|
||||
else if(exists == true && shouldExist == false)
|
||||
{
|
||||
callback({stop: "padID does already exist"});
|
||||
callback(new customError("padID does already exist","apierror"));
|
||||
}
|
||||
//pad exists, let's get it
|
||||
else
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
|
||||
|
@ -29,7 +30,8 @@ exports.doesAuthorExists = function (authorID, callback)
|
|||
//check if the database entry of this author exists
|
||||
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)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
//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)
|
||||
{
|
||||
//error?
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//set the name of this author
|
||||
if(name)
|
||||
|
@ -84,24 +82,14 @@ function mapAuthorWithDBKey (mapperkey, mapper, callback)
|
|||
//try to map to an author
|
||||
db.get(mapperkey + ":" + mapper, function (err, author)
|
||||
{
|
||||
//error?
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//there is no author with this mapper, so create one
|
||||
if(author == null)
|
||||
{
|
||||
exports.createAuthor(null, function(err, author)
|
||||
{
|
||||
//error?
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//create the token2author relation
|
||||
db.set(mapperkey + ":" + mapper, author.authorID);
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var customError = require("../utils/customError");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var padManager = require("./PadManager");
|
||||
|
@ -34,15 +36,12 @@ exports.deleteGroup = function(groupID, callback)
|
|||
//try to get the group entry
|
||||
db.get("group:" + groupID, function (err, _group)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//group does not exist
|
||||
else if(_group == null)
|
||||
if(_group == null)
|
||||
{
|
||||
callback({stop: "groupID does not exist"});
|
||||
callback(new customError("groupID does not exist","apierror"));
|
||||
}
|
||||
//group exists, everything is fine
|
||||
else
|
||||
|
@ -67,7 +66,7 @@ exports.deleteGroup = function(groupID, callback)
|
|||
{
|
||||
padManager.getPad(padID, function(err, pad)
|
||||
{
|
||||
if(err) {callback(err); return}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
pad.remove(callback);
|
||||
});
|
||||
|
@ -79,7 +78,7 @@ exports.deleteGroup = function(groupID, callback)
|
|||
//try to get the group entry
|
||||
db.get("group2sessions:" + groupID, function (err, group2sessions)
|
||||
{
|
||||
if(err) {callback(err); return}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//skip if there is no group2sessions entry
|
||||
if(group2sessions == null) {callback(); return}
|
||||
|
@ -107,7 +106,8 @@ exports.deleteGroup = function(groupID, callback)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
callback(err);
|
||||
if(ERR(err, callback)) return;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,8 @@ exports.doesGroupExist = function(groupID, callback)
|
|||
//try to get the group entry
|
||||
db.get("group:" + groupID, function (err, group)
|
||||
{
|
||||
callback(err, group != null);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, group != null);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -135,30 +136,21 @@ exports.createGroupIfNotExistsFor = function(groupMapper, callback)
|
|||
//ensure mapper is optional
|
||||
if(typeof groupMapper != "string")
|
||||
{
|
||||
callback({stop: "groupMapper is no string"});
|
||||
callback(new customError("groupMapper is no string","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//try to get a group for this mapper
|
||||
db.get("mapper2group:"+groupMapper, function(err, groupID)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//there is no group for this mapper, let's create a group
|
||||
if(groupID == null)
|
||||
{
|
||||
exports.createGroup(function(err, responseObj)
|
||||
{
|
||||
//check for errors
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//create the mapper entry for this group
|
||||
db.set("mapper2group:"+groupMapper, responseObj.groupID);
|
||||
|
@ -169,7 +161,8 @@ exports.createGroupIfNotExistsFor = function(groupMapper, callback)
|
|||
//there is a group for this mapper, let's return it
|
||||
else
|
||||
{
|
||||
callback(err, {groupID: groupID});
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, {groupID: groupID});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -185,15 +178,12 @@ exports.createGroupPad = function(groupID, padName, text, callback)
|
|||
{
|
||||
exports.doesGroupExist(groupID, function(err, exists)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//group does not exist
|
||||
else if(exists == false)
|
||||
if(exists == false)
|
||||
{
|
||||
callback({stop: "groupID does not exist"});
|
||||
callback(new customError("groupID does not exist","apierror"));
|
||||
}
|
||||
//group exists, everything is fine
|
||||
else
|
||||
|
@ -207,15 +197,12 @@ exports.createGroupPad = function(groupID, padName, text, callback)
|
|||
{
|
||||
padManager.doesPadExists(padID, function(err, exists)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//pad exists already
|
||||
else if(exists == true)
|
||||
if(exists == true)
|
||||
{
|
||||
callback({stop: "padName does already exist"});
|
||||
callback(new customError("padName does already exist","apierror"));
|
||||
}
|
||||
//pad does not exist, everything is fine
|
||||
else
|
||||
|
@ -229,7 +216,8 @@ exports.createGroupPad = function(groupID, padName, text, callback)
|
|||
{
|
||||
padManager.getPad(padID, text, function(err)
|
||||
{
|
||||
callback(err);
|
||||
if(ERR(err, callback)) return;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//create an entry in the group for this pad
|
||||
|
@ -240,7 +228,8 @@ exports.createGroupPad = function(groupID, padName, text, callback)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
callback(err, {padID: padID});
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, {padID: padID});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -248,22 +237,20 @@ exports.listPads = function(groupID, callback)
|
|||
{
|
||||
exports.doesGroupExist(groupID, function(err, exists)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//group does not exist
|
||||
else if(exists == false)
|
||||
if(exists == false)
|
||||
{
|
||||
callback({stop: "groupID does not exist"});
|
||||
callback(new customError("groupID does not exist","apierror"));
|
||||
}
|
||||
//group exists, let's get the pads
|
||||
else
|
||||
{
|
||||
db.getSub("group:" + groupID, ["pads"], function(err, pads)
|
||||
{
|
||||
callback(err, {padIDs: pads});
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, {padIDs: pads});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
require('joose');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var Changeset = require("../utils/Changeset");
|
||||
var AttributePoolFactory = require("../utils/AttributePoolFactory");
|
||||
var db = require("./DB").db;
|
||||
|
@ -164,8 +165,9 @@ Class('Pad', {
|
|||
{
|
||||
db.getSub("pad:"+_this.id+":revs:"+keyRev, ["meta", "atext"], function(err, _atext)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
atext = Changeset.cloneAText(_atext);
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//get all needed changesets
|
||||
|
@ -175,8 +177,9 @@ Class('Pad', {
|
|||
{
|
||||
_this.getRevisionChangeset(item, function(err, changeset)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
changesets[item] = changeset;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
}
|
||||
|
@ -199,7 +202,8 @@ Class('Pad', {
|
|||
}
|
||||
], 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)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
entry = _entry;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//add the authorName
|
||||
|
@ -264,13 +269,15 @@ Class('Pad', {
|
|||
//get the authorName
|
||||
authorManager.getAuthorName(entry.userId, function(err, authorName)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
entry.userName = authorName;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], 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)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
entries[entryObject.order] = entry;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, function(err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//sort out broken chat entries
|
||||
//it looks like in happend in the past that the chat head was
|
||||
//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);
|
||||
}
|
||||
|
||||
callback(err, cleanedEntries);
|
||||
callback(null, cleanedEntries);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -345,11 +355,7 @@ Class('Pad', {
|
|||
//try to load the pad
|
||||
db.get("pad:"+this.id, function(err, value)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err, null);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//if this pad exists, load it
|
||||
if(value != null)
|
||||
|
@ -410,7 +416,7 @@ Class('Pad', {
|
|||
|
||||
db.get("group:" + groupID, function (err, group)
|
||||
{
|
||||
if(err) {callback(err); return}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//remove the pad entry
|
||||
delete group.pads[padID];
|
||||
|
@ -432,7 +438,7 @@ Class('Pad', {
|
|||
{
|
||||
readOnlyManager.getReadOnlyId(padID, function(err, readonlyID)
|
||||
{
|
||||
if(err) {callback(err); return}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
db.remove("pad2readonly:" + padID);
|
||||
db.remove("readonly2pad:" + readonlyID);
|
||||
|
@ -475,7 +481,8 @@ Class('Pad', {
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
callback(err);
|
||||
if(ERR(err, callback)) return;
|
||||
callback();
|
||||
})
|
||||
},
|
||||
//set in db
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var customError = require("../utils/customError");
|
||||
require("../db/Pad");
|
||||
var db = require("./DB").db;
|
||||
|
||||
|
@ -30,12 +32,20 @@ var db = require("./DB").db;
|
|||
* If this is needed in other places, it would be wise to make this a prototype
|
||||
* that's defined somewhere more sensible.
|
||||
*/
|
||||
globalPads = {
|
||||
var globalPads = {
|
||||
get: function (name) { return this[':'+name]; },
|
||||
set: function (name, value) { this[':'+name] = value; },
|
||||
remove: function (name) { delete this[':'+name]; }
|
||||
};
|
||||
|
||||
/**
|
||||
* An array of padId transformations. These represent changes in pad name policy over
|
||||
* time, and allow us to "play back" these changes so legacy padIds can be found.
|
||||
*/
|
||||
var padIdTransforms = [
|
||||
[/\s+/g, '_']
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns a Pad Object with the callback
|
||||
* @param id A String with the id of the pad
|
||||
|
@ -46,7 +56,7 @@ exports.getPad = function(id, text, callback)
|
|||
//check if this is a valid padId
|
||||
if(!exports.isValidPadId(id))
|
||||
{
|
||||
callback({stop: id + " is not a valid padId"});
|
||||
callback(new customError(id + " is not a valid padId","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -63,14 +73,14 @@ exports.getPad = function(id, text, callback)
|
|||
//check if text is a string
|
||||
if(typeof text != "string")
|
||||
{
|
||||
callback({stop: "text is not a string"});
|
||||
callback(new customError("text is not a string","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//check if text is less than 100k chars
|
||||
if(text.length > 100000)
|
||||
{
|
||||
callback({stop: "text must be less than 100k chars"});
|
||||
callback(new customError("text must be less than 100k chars","apierror"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -90,15 +100,10 @@ exports.getPad = function(id, text, callback)
|
|||
//initalize the pad
|
||||
pad.init(text, function(err)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
globalPads.set(id, pad);
|
||||
callback(null, pad);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -108,10 +113,44 @@ exports.doesPadExists = function(padId, callback)
|
|||
{
|
||||
db.get("pad:"+padId, function(err, value)
|
||||
{
|
||||
callback(err, value != null);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, value != null);
|
||||
});
|
||||
}
|
||||
|
||||
//returns a sanitized padId, respecting legacy pad id formats
|
||||
exports.sanitizePadId = function(padId, callback) {
|
||||
var transform_index = arguments[2] || 0;
|
||||
//we're out of possible transformations, so just return it
|
||||
if(transform_index >= padIdTransforms.length)
|
||||
{
|
||||
callback(padId);
|
||||
}
|
||||
//check if padId exists
|
||||
else
|
||||
{
|
||||
exports.doesPadExists(padId, function(junk, exists)
|
||||
{
|
||||
if(exists)
|
||||
{
|
||||
callback(padId);
|
||||
}
|
||||
else
|
||||
{
|
||||
//get the next transformation *that's different*
|
||||
var transformedPadId = padId;
|
||||
while(transformedPadId == padId && transform_index < padIdTransforms.length)
|
||||
{
|
||||
transformedPadId = padId.replace(padIdTransforms[transform_index][0], padIdTransforms[transform_index][1]);
|
||||
transform_index += 1;
|
||||
}
|
||||
//check the next transform
|
||||
exports.sanitizePadId(transformedPadId, callback, transform_index);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.isValidPadId = function(padId)
|
||||
{
|
||||
return /^(g.[a-zA-Z0-9]{16}\$)?[^$]{1,50}$/.test(padId);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
|
||||
|
@ -55,8 +56,9 @@ exports.getReadOnlyId = function (padId, callback)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
//return the results
|
||||
callback(err, readOnlyId);
|
||||
callback(null, readOnlyId);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var authorManager = require("./AuthorManager");
|
||||
|
@ -56,6 +57,8 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
|
|||
//get author for this token
|
||||
authorManager.getAuthor4Token(token, function(err, author)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
// assume user has access
|
||||
statusObject = {accessStatus: "grant", authorID: author};
|
||||
// user can't create pads
|
||||
|
@ -64,17 +67,19 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
|
|||
// check if pad exists
|
||||
padManager.doesPadExists(padID, function(err, exists)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
// pad doesn't exist - user can't have access
|
||||
if(!exists) statusObject.accessStatus = "deny";
|
||||
// grant or deny access, with author of token
|
||||
callback(err, statusObject);
|
||||
callback(null, statusObject);
|
||||
});
|
||||
}
|
||||
// user may create new pads - no need to check anything
|
||||
else
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
padExists = exists;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//get informations about this session
|
||||
|
@ -112,13 +118,13 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
|
|||
sessionManager.getSessionInfo(sessionID, function(err, sessionInfo)
|
||||
{
|
||||
//skip session validation if the session doesn't exists
|
||||
if(err && err.stop == "sessionID does not exist")
|
||||
if(err && err.message == "sessionID does not exist")
|
||||
{
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
if(err) {callback(err); return}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
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
|
||||
authorManager.getAuthor4Token(token, function(err, author)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
tokenAuthor = author;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
|
@ -157,7 +164,7 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
|
|||
|
||||
padManager.getPad(padID, function(err, pad)
|
||||
{
|
||||
if(err) {callback(err); return}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//is it a public pad?
|
||||
isPublic = pad.getPublicStatus();
|
||||
|
@ -265,6 +272,7 @@ exports.checkAccess = function (padID, sessionID, token, password, callback)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
callback(err, statusObject);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, statusObject);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var customError = require("../utils/customError");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var groupMangager = require("./GroupManager");
|
||||
|
@ -28,7 +30,8 @@ exports.doesSessionExist = function(sessionID, callback)
|
|||
//check if the database entry of this session exists
|
||||
db.get("session:" + sessionID, function (err, session)
|
||||
{
|
||||
callback(err, session != null);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, session != null);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -45,15 +48,12 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
|||
{
|
||||
groupMangager.doesGroupExist(groupID, function(err, exists)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//group does not exist
|
||||
else if(exists == false)
|
||||
if(exists == false)
|
||||
{
|
||||
callback({stop: "groupID does not exist"});
|
||||
callback(new customError("groupID does not exist","apierror"));
|
||||
}
|
||||
//everything is fine, continue
|
||||
else
|
||||
|
@ -67,15 +67,12 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
|||
{
|
||||
authorMangager.doesAuthorExists(authorID, function(err, exists)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//author does not exist
|
||||
else if(exists == false)
|
||||
if(exists == false)
|
||||
{
|
||||
callback({stop: "authorID does not exist"});
|
||||
callback(new customError("authorID does not exist","apierror"));
|
||||
}
|
||||
//everything is fine, continue
|
||||
else
|
||||
|
@ -97,7 +94,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
|||
}
|
||||
else
|
||||
{
|
||||
callback({stop: "validUntil is not a number"});
|
||||
callback(new customError("validUntil is not a number","apierror"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -105,21 +102,21 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
|||
//ensure this is not a negativ number
|
||||
if(validUntil < 0)
|
||||
{
|
||||
callback({stop: "validUntil is a negativ number"});
|
||||
callback(new customError("validUntil is a negativ number","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//ensure this is not a float value
|
||||
if(!is_int(validUntil))
|
||||
{
|
||||
callback({stop: "validUntil is a float value"});
|
||||
callback(new customError("validUntil is a float value","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
//check if validUntil is in the future
|
||||
if(Math.floor(new Date().getTime()/1000) > validUntil)
|
||||
{
|
||||
callback({stop: "validUntil is in the past"});
|
||||
callback(new customError("validUntil is in the past","apierror"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -137,12 +134,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
|||
//get the entry
|
||||
db.get("group2sessions:" + groupID, function(err, group2sessions)
|
||||
{
|
||||
//did a error happen?
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//the entry doesn't exist so far, let's create it
|
||||
if(group2sessions == null)
|
||||
|
@ -165,12 +157,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
|||
//get the entry
|
||||
db.get("author2sessions:" + authorID, function(err, author2sessions)
|
||||
{
|
||||
//did a error happen?
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//the entry doesn't exist so far, let's create it
|
||||
if(author2sessions == null)
|
||||
|
@ -189,8 +176,10 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//return error and sessionID
|
||||
callback(err, {sessionID: sessionID});
|
||||
callback(null, {sessionID: sessionID});
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -199,15 +188,12 @@ exports.getSessionInfo = function(sessionID, callback)
|
|||
//check if the database entry of this session exists
|
||||
db.get("session:" + sessionID, function (err, session)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//session does not exists
|
||||
else if(session == null)
|
||||
if(session == null)
|
||||
{
|
||||
callback({stop: "sessionID does not exist"})
|
||||
callback(new customError("sessionID does not exist","apierror"))
|
||||
}
|
||||
//everything is fine, return the sessioninfos
|
||||
else
|
||||
|
@ -231,15 +217,12 @@ exports.deleteSession = function(sessionID, callback)
|
|||
//get the session entry
|
||||
db.get("session:" + sessionID, function (err, session)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//session does not exists
|
||||
else if(session == null)
|
||||
if(session == null)
|
||||
{
|
||||
callback({stop: "sessionID does not exist"})
|
||||
callback(new customError("sessionID does not exist","apierror"))
|
||||
}
|
||||
//everything is fine, return the sessioninfos
|
||||
else
|
||||
|
@ -256,8 +239,9 @@ exports.deleteSession = function(sessionID, callback)
|
|||
{
|
||||
db.get("group2sessions:" + groupID, function (err, _group2sessions)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
group2sessions = _group2sessions;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//get the author2sessions entry
|
||||
|
@ -265,8 +249,9 @@ exports.deleteSession = function(sessionID, callback)
|
|||
{
|
||||
db.get("author2sessions:" + authorID, function (err, _author2sessions)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
author2sessions = _author2sessions;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//remove the values from the database
|
||||
|
@ -287,7 +272,8 @@ exports.deleteSession = function(sessionID, callback)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
callback(err);
|
||||
if(ERR(err, callback)) return;
|
||||
callback();
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -295,15 +281,12 @@ exports.listSessionsOfGroup = function(groupID, callback)
|
|||
{
|
||||
groupMangager.doesGroupExist(groupID, function(err, exists)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//group does not exist
|
||||
else if(exists == false)
|
||||
if(exists == false)
|
||||
{
|
||||
callback({stop: "groupID does not exist"});
|
||||
callback(new customError("groupID does not exist","apierror"));
|
||||
}
|
||||
//everything is fine, continue
|
||||
else
|
||||
|
@ -317,15 +300,12 @@ exports.listSessionsOfAuthor = function(authorID, callback)
|
|||
{
|
||||
authorMangager.doesAuthorExists(authorID, function(err, exists)
|
||||
{
|
||||
//error
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//group does not exist
|
||||
else if(exists == false)
|
||||
if(exists == false)
|
||||
{
|
||||
callback({stop: "authorID does not exist"});
|
||||
callback(new customError("authorID does not exist","apierror"));
|
||||
}
|
||||
//everything is fine, continue
|
||||
else
|
||||
|
@ -346,8 +326,9 @@ function listSessionsWithDBKey (dbkey, callback)
|
|||
//get the group2sessions entry
|
||||
db.get(dbkey, function(err, sessionObject)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
sessions = sessionObject ? sessionObject.sessionIDs : null;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function(callback)
|
||||
|
@ -364,14 +345,16 @@ function listSessionsWithDBKey (dbkey, callback)
|
|||
{
|
||||
exports.getSessionInfo(sessionID, function(err, sessionInfo)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
sessions[sessionID] = sessionInfo;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
callback(err, sessions);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, sessions);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var Changeset = require('./Changeset');
|
||||
var AttributePoolFactory = require("./AttributePoolFactory");
|
||||
var Changeset = require('./utils/Changeset');
|
||||
var AttributePoolFactory = require("./utils/AttributePoolFactory");
|
||||
|
||||
function random() {
|
||||
this.nextInt = function (maxValue) {
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var fs = require("fs");
|
||||
var api = require("../db/API");
|
||||
var padManager = require("../db/PadManager");
|
||||
|
||||
//ensure we have an apikey
|
||||
var apikey = null;
|
||||
|
@ -95,6 +97,32 @@ exports.handle = function(functionName, fields, req, res)
|
|||
return;
|
||||
}
|
||||
|
||||
//sanitize any pad id's before continuing
|
||||
if(fields["padID"])
|
||||
{
|
||||
padManager.sanitizePadId(fields["padID"], function(padId)
|
||||
{
|
||||
fields["padID"] = padId;
|
||||
callAPI(functionName, fields, req, res);
|
||||
});
|
||||
}
|
||||
else if(fields["padName"])
|
||||
{
|
||||
padManager.sanitizePadId(fields["padName"], function(padId)
|
||||
{
|
||||
fields["padName"] = padId;
|
||||
callAPI(functionName, fields, req, res);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
callAPI(functionName, fields, req, res);
|
||||
}
|
||||
}
|
||||
|
||||
//calls the api function
|
||||
function callAPI(functionName, fields, req, res)
|
||||
{
|
||||
//put the function parameters in an array
|
||||
var functionParams = [];
|
||||
for(var i=0;i<functions[functionName].length;i++)
|
||||
|
@ -114,15 +142,15 @@ exports.handle = function(functionName, fields, req, res)
|
|||
res.send({code: 0, message: "ok", data: data});
|
||||
}
|
||||
// parameters were wrong and the api stopped execution, pass the error
|
||||
else if(err.stop)
|
||||
else if(err.name == "apierror")
|
||||
{
|
||||
res.send({code: 1, message: err.stop, data: null});
|
||||
res.send({code: 1, message: err.message, data: null});
|
||||
}
|
||||
//an unkown error happend
|
||||
else
|
||||
{
|
||||
res.send({code: 2, message: "internal error", data: null});
|
||||
throw (err);
|
||||
ERR(err);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var exporthtml = require("../utils/ExportHtml");
|
||||
var exportdokuwiki = require("../utils/ExportDokuWiki");
|
||||
var padManager = require("../db/PadManager");
|
||||
var async = require("async");
|
||||
var fs = require("fs");
|
||||
|
@ -50,10 +52,37 @@ exports.doExport = function(req, res, padId, type)
|
|||
{
|
||||
padManager.getPad(padId, function(err, pad)
|
||||
{
|
||||
if(err)
|
||||
throw err;
|
||||
|
||||
ERR(err);
|
||||
if(req.params.rev){
|
||||
pad.getInternalRevisionAText(req.params.rev, function(junk, text)
|
||||
{
|
||||
res.send(text.text ? text.text : null);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
res.send(pad.text());
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(type == 'dokuwiki')
|
||||
{
|
||||
var randNum;
|
||||
var srcFile, destFile;
|
||||
|
||||
async.series([
|
||||
//render the dokuwiki document
|
||||
function(callback)
|
||||
{
|
||||
exportdokuwiki.getPadDokuWikiDocument(padId, req.params.rev, function(err, dokuwiki)
|
||||
{
|
||||
res.send(dokuwiki);
|
||||
callback("stop");
|
||||
});
|
||||
},
|
||||
], function(err)
|
||||
{
|
||||
if(err && err != "stop") throw err;
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -66,10 +95,11 @@ exports.doExport = function(req, res, padId, type)
|
|||
//render the html document
|
||||
function(callback)
|
||||
{
|
||||
exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
|
||||
exporthtml.getPadHTMLDocument(padId, req.params.rev, false, function(err, _html)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
html = _html;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//decide what to do with the html export
|
||||
|
@ -120,12 +150,16 @@ exports.doExport = function(req, res, padId, type)
|
|||
fs.unlink(destFile, callback);
|
||||
}, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
fs.unlink(destFile, callback);
|
||||
}
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err && err != "stop") throw err;
|
||||
if(err && err != "stop") ERR(err);
|
||||
})
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var padManager = require("../db/PadManager");
|
||||
var padMessageHandler = require("./PadMessageHandler");
|
||||
var async = require("async");
|
||||
|
@ -122,8 +123,9 @@ exports.doImport = function(req, res, padId)
|
|||
{
|
||||
padManager.getPad(padId, function(err, _pad)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
pad = _pad;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -132,6 +134,7 @@ exports.doImport = function(req, res, padId)
|
|||
{
|
||||
fs.readFile(destFile, "utf8", function(err, _text)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
text = _text;
|
||||
|
||||
//node on windows has a delay on releasing of the file lock.
|
||||
|
@ -140,9 +143,13 @@ exports.doImport = function(req, res, padId)
|
|||
{
|
||||
setTimeout(function()
|
||||
{
|
||||
callback(err);
|
||||
callback();
|
||||
}, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -176,7 +183,7 @@ exports.doImport = function(req, res, padId)
|
|||
return;
|
||||
}
|
||||
|
||||
if(err) throw err;
|
||||
ERR(err);
|
||||
|
||||
//close the connection
|
||||
res.send("ok");
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var async = require("async");
|
||||
var padManager = require("../db/PadManager");
|
||||
var Changeset = require("../utils/Changeset");
|
||||
|
@ -27,7 +28,6 @@ var readOnlyManager = require("../db/ReadOnlyManager");
|
|||
var settings = require('../utils/Settings');
|
||||
var securityManager = require("../db/SecurityManager");
|
||||
var log4js = require('log4js');
|
||||
var os = require("os");
|
||||
var messageLogger = log4js.getLogger("message");
|
||||
|
||||
/**
|
||||
|
@ -107,7 +107,7 @@ exports.handleDisconnect = function(client)
|
|||
//get the author color out of the db
|
||||
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
|
||||
var messageToTheOtherUsers = {
|
||||
|
@ -218,16 +218,18 @@ function handleChatMessage(client, message)
|
|||
{
|
||||
padManager.getPad(padId, function(err, _pad)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
pad = _pad;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
authorManager.getAuthorName(userId, function(err, _userName)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
userName = _userName;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//save the chat message and broadcast it
|
||||
|
@ -257,7 +259,7 @@ function handleChatMessage(client, message)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err) throw err;
|
||||
ERR(err);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -375,8 +377,9 @@ function handleUserChanges(client, message)
|
|||
{
|
||||
padManager.getPad(session2pad[client.id], function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
pad = value;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//create the changeset
|
||||
|
@ -422,16 +425,10 @@ function handleUserChanges(client, message)
|
|||
|
||||
pad.getRevisionChangeset(r, function(err, c)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
changeset = Changeset.follow(c, changeset, false, apool);
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
},
|
||||
//use the callback of the series function
|
||||
|
@ -469,7 +466,7 @@ function handleUserChanges(client, message)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err) throw err;
|
||||
ERR(err);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -502,25 +499,23 @@ exports.updatePadClients = function(pad, callback)
|
|||
{
|
||||
pad.getRevisionAuthor(r, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
author = value;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function (callback)
|
||||
{
|
||||
pad.getRevisionChangeset(r, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
revChangeset = value;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
if(author == sessioninfos[session].author)
|
||||
{
|
||||
|
@ -633,7 +628,7 @@ function handleClientReady(client, message)
|
|||
{
|
||||
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
|
||||
if(statusObject.accessStatus == "grant")
|
||||
|
@ -657,8 +652,9 @@ function handleClientReady(client, message)
|
|||
{
|
||||
authorManager.getAuthorColorId(author, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
authorColorId = value;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//get author name
|
||||
|
@ -666,24 +662,27 @@ function handleClientReady(client, message)
|
|||
{
|
||||
authorManager.getAuthorName(author, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
authorName = value;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
padManager.getPad(message.padId, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
pad = value;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
readOnlyManager.getReadOnlyId(message.padId, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
readOnlyId = value;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
|
@ -701,9 +700,10 @@ function handleClientReady(client, message)
|
|||
{
|
||||
authorManager.getAuthor(authorId, function(err, author)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
delete author.timestamp;
|
||||
historicalAuthorData[authorId] = author;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
},
|
||||
|
@ -712,8 +712,9 @@ function handleClientReady(client, message)
|
|||
{
|
||||
pad.getLastChatMessages(100, function(err, _chatMessages)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
chatMessages = _chatMessages;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
|
@ -753,13 +754,6 @@ function handleClientReady(client, message)
|
|||
var apool = attribsForWire.pool.toJsonable();
|
||||
atext.attribs = attribsForWire.translated;
|
||||
|
||||
//check if abiword is avaiable
|
||||
var abiwordAvailable = settings.abiword != null ? "yes" : "no";
|
||||
if(settings.abiword != null && os.type().indexOf("Windows") != -1)
|
||||
{
|
||||
abiwordAvailable = "withoutPDF";
|
||||
}
|
||||
|
||||
var clientVars = {
|
||||
"accountPrivs": {
|
||||
"maxRevisions": 100
|
||||
|
@ -796,7 +790,7 @@ function handleClientReady(client, message)
|
|||
"fullWidth": false,
|
||||
"hideSidebar": false
|
||||
},
|
||||
"abiwordAvailable": abiwordAvailable,
|
||||
"abiwordAvailable": settings.abiwordAvailable(),
|
||||
"hooks": {}
|
||||
}
|
||||
|
||||
|
@ -806,6 +800,8 @@ function handleClientReady(client, message)
|
|||
clientVars.userName = authorName;
|
||||
}
|
||||
|
||||
if(sessioninfos[client.id] !== undefined)
|
||||
{
|
||||
//This is a reconnect, so we don't have to send the client the ClientVars again
|
||||
if(message.reconnect == true)
|
||||
{
|
||||
|
@ -822,8 +818,8 @@ function handleClientReady(client, message)
|
|||
}
|
||||
|
||||
//Save the revision and the author id in sessioninfos
|
||||
sessioninfos[client.id].rev = pad.getHeadRevisionNumber();
|
||||
sessioninfos[client.id].author = author;
|
||||
}
|
||||
|
||||
//prepare the notification for the other users on the pad, that this user joined
|
||||
var messageToTheOtherUsers = {
|
||||
|
@ -859,16 +855,18 @@ function handleClientReady(client, message)
|
|||
{
|
||||
authorManager.getAuthorColorId(sessioninfos[sessionID].author, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
sessionAuthorColorId = value;
|
||||
callback(err);
|
||||
callback();
|
||||
})
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
authorManager.getAuthorName(sessioninfos[sessionID].author, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
sessionAuthorName = value;
|
||||
callback(err);
|
||||
callback();
|
||||
})
|
||||
}
|
||||
],callback);
|
||||
|
@ -903,6 +901,6 @@ function handleClientReady(client, message)
|
|||
}
|
||||
],function(err)
|
||||
{
|
||||
if(err) throw err;
|
||||
ERR(err);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var log4js = require('log4js');
|
||||
var messageLogger = log4js.getLogger("message");
|
||||
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)
|
||||
{
|
||||
if(err) throw err;
|
||||
ERR(err);
|
||||
|
||||
//access was granted, mark the client as authorized and handle the message
|
||||
if(statusObject.accessStatus == "grant")
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var async = require("async");
|
||||
var padManager = require("../db/PadManager");
|
||||
var Changeset = require("../utils/Changeset");
|
||||
var AttributePoolFactory = require("../utils/AttributePoolFactory");
|
||||
var settings = require('../utils/Settings');
|
||||
var authorManager = require("../db/AuthorManager");
|
||||
var log4js = require('log4js');
|
||||
var messageLogger = log4js.getLogger("message");
|
||||
|
@ -92,7 +94,7 @@ function handleClientReady(client, message)
|
|||
//send the timeslider client the clientVars, with this values its able to start
|
||||
createTimesliderClientVars (message.padId, function(err, clientVars)
|
||||
{
|
||||
if(err) throw err;
|
||||
ERR(err);
|
||||
|
||||
client.json.send({type: "CLIENT_VARS", data: clientVars});
|
||||
})
|
||||
|
@ -138,7 +140,7 @@ function handleChangesetRequest(client, message)
|
|||
//build the requested rough changesets and send them back
|
||||
getChangesetInfo(padId, start, end, granularity, function(err, changesetInfo)
|
||||
{
|
||||
if(err) throw err;
|
||||
ERR(err);
|
||||
|
||||
var data = changesetInfo;
|
||||
data.requestID = message.data.requestID;
|
||||
|
@ -159,6 +161,7 @@ function createTimesliderClientVars (padId, callback)
|
|||
fullWidth: false,
|
||||
disableRightBar: false,
|
||||
initialChangesets: [],
|
||||
abiwordAvailable: settings.abiwordAvailable(),
|
||||
hooks: [],
|
||||
initialStyledContents: {}
|
||||
};
|
||||
|
@ -171,8 +174,9 @@ function createTimesliderClientVars (padId, callback)
|
|||
{
|
||||
padManager.getPad(padId, function(err, _pad)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
pad = _pad;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//get all authors and add them to
|
||||
|
@ -187,15 +191,17 @@ function createTimesliderClientVars (padId, callback)
|
|||
{
|
||||
authorManager.getAuthor(authorId, function(err, author)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
historicalAuthorData[authorId] = author;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, function(err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
//add historicalAuthorData to the clientVars and continue
|
||||
clientVars.historicalAuthorData = historicalAuthorData;
|
||||
clientVars.initialStyledContents.historicalAuthorData = historicalAuthorData;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//get the timestamp of the last revision
|
||||
|
@ -203,8 +209,9 @@ function createTimesliderClientVars (padId, callback)
|
|||
{
|
||||
pad.getRevisionDate(pad.getHeadRevisionNumber(), function(err, date)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
clientVars.currentTime = date;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function(callback)
|
||||
|
@ -235,14 +242,16 @@ function createTimesliderClientVars (padId, callback)
|
|||
Math.floor(lastRev / topGranularity)*topGranularity+topGranularity, granularity,
|
||||
function(err, changeset)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
clientVars.initialChangesets.push(changeset);
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
callback(err, clientVars);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, clientVars);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -267,8 +276,9 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
|||
{
|
||||
padManager.getPad(padId, function(err, _pad)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
pad = _pad;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function(callback)
|
||||
|
@ -309,8 +319,9 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
|||
{
|
||||
composePadChangesets(padId, item.start, item.end, function(err, changeset)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
composedChangesets[item.start + "/" + item.end] = changeset;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
},
|
||||
|
@ -321,8 +332,9 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
|||
{
|
||||
pad.getRevisionDate(revNum, function(err, revDate)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
revisionDate[revNum] = Math.floor(revDate/1000);
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
},
|
||||
|
@ -331,8 +343,9 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
|||
{
|
||||
getPadLines(padId, startNum-1, function(err, _lines)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
lines = _lines;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
|
@ -383,12 +396,8 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err)
|
||||
{
|
||||
callback(err);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
callback(null, {forwardsChangesets: forwardsChangesets,
|
||||
backwardsChangesets: backwardsChangesets,
|
||||
apool: apool.toJsonable(),
|
||||
|
@ -396,7 +405,6 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
|||
timeDeltas: timeDeltas,
|
||||
start: startNum,
|
||||
granularity: granularity });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -416,8 +424,9 @@ function getPadLines(padId, revNum, callback)
|
|||
{
|
||||
padManager.getPad(padId, function(err, _pad)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
pad = _pad;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//get the atext
|
||||
|
@ -427,8 +436,9 @@ function getPadLines(padId, revNum, callback)
|
|||
{
|
||||
pad.getInternalRevisionAText(revNum, function(err, _atext)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
atext = _atext;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -445,7 +455,8 @@ function getPadLines(padId, revNum, callback)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
callback(err, result);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, result);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -465,8 +476,9 @@ function composePadChangesets(padId, startNum, endNum, callback)
|
|||
{
|
||||
padManager.getPad(padId, function(err, _pad)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
pad = _pad;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//fetch all changesets we need
|
||||
|
@ -486,8 +498,9 @@ function composePadChangesets(padId, startNum, endNum, callback)
|
|||
{
|
||||
pad.getRevisionChangeset(revNum, function(err, value)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
changesets[revNum] = value;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},callback);
|
||||
},
|
||||
|
@ -509,7 +522,7 @@ function composePadChangesets(padId, startNum, endNum, callback)
|
|||
//return err and changeset
|
||||
function(err)
|
||||
{
|
||||
if(err) throw err;
|
||||
callback(err, changeset);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, changeset);
|
||||
});
|
||||
}
|
||||
|
|
107
node/server.js
107
node/server.js
|
@ -20,6 +20,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var log4js = require('log4js');
|
||||
var os = require("os");
|
||||
var socketio = require('socket.io');
|
||||
|
@ -91,6 +92,9 @@ async.waterfall([
|
|||
var httpLogger = log4js.getLogger("http");
|
||||
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.
|
||||
// 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"))
|
||||
|
@ -98,6 +102,12 @@ async.waterfall([
|
|||
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
|
||||
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)
|
||||
{
|
||||
if(err) throw err;
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//there is access, continue
|
||||
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
|
||||
app.get('/ro/:id', function(req, res)
|
||||
{
|
||||
|
@ -159,12 +189,14 @@ async.waterfall([
|
|||
{
|
||||
readOnlyManager.getPadId(req.params.id, function(err, _padId)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
padId = _padId;
|
||||
|
||||
//we need that to tell hasPadAcess about the pad
|
||||
req.params.pad = padId;
|
||||
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//render the html document
|
||||
|
@ -182,8 +214,9 @@ async.waterfall([
|
|||
//render the html document
|
||||
exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
html = _html;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -191,7 +224,7 @@ async.waterfall([
|
|||
{
|
||||
//throw any unexpected error
|
||||
if(err && err != "notfound")
|
||||
throw err;
|
||||
ERR(err);
|
||||
|
||||
if(err == "notfound")
|
||||
res.send('404 - Not Found', 404);
|
||||
|
@ -200,47 +233,57 @@ async.waterfall([
|
|||
});
|
||||
});
|
||||
|
||||
//serve pad.html under /p
|
||||
app.get('/p/:pad', function(req, res, next)
|
||||
{
|
||||
//redirects browser to the pad's sanitized url if needed. otherwise, renders the html
|
||||
function goToPad(req, res, render) {
|
||||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
padManager.sanitizePadId(req.params.pad, function(padId) {
|
||||
//the pad id was sanitized, so we redirect to the sanitized version
|
||||
if(padId != req.params.pad)
|
||||
{
|
||||
var real_path = req.path.replace(/^\/p\/[^\/]+/, '/p/' + padId);
|
||||
res.header('Location', real_path);
|
||||
res.send('You should be redirected to <a href="' + real_path + '">' + real_path + '</a>', 302);
|
||||
}
|
||||
//the pad id was fine, so just render it
|
||||
else
|
||||
{
|
||||
render();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//serve pad.html under /p
|
||||
app.get('/p/:pad', function(req, res, next)
|
||||
{
|
||||
goToPad(req, res, function() {
|
||||
res.header("Server", serverName);
|
||||
var filePath = path.normalize(__dirname + "/../static/pad.html");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
});
|
||||
|
||||
//serve timeslider.html under /p/$padname/timeslider
|
||||
app.get('/p/:pad/timeslider', function(req, res, next)
|
||||
{
|
||||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
return;
|
||||
}
|
||||
|
||||
goToPad(req, res, function() {
|
||||
res.header("Server", serverName);
|
||||
var filePath = path.normalize(__dirname + "/../static/timeslider.html");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
});
|
||||
|
||||
//serve timeslider.html under /p/$padname/timeslider
|
||||
app.get('/p/:pad/export/:type', function(req, res, next)
|
||||
app.get('/p/:pad/:rev?/export/:type', function(req, res, next)
|
||||
{
|
||||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
return;
|
||||
}
|
||||
|
||||
var types = ["pdf", "doc", "txt", "html", "odt"];
|
||||
goToPad(req, res, function() {
|
||||
var types = ["pdf", "doc", "txt", "html", "odt", "dokuwiki"];
|
||||
//send a 404 if we don't support this filetype
|
||||
if(types.indexOf(req.params.type) == -1)
|
||||
{
|
||||
|
@ -249,7 +292,8 @@ async.waterfall([
|
|||
}
|
||||
|
||||
//if abiword is disabled, and this is a format we only support with abiword, output a message
|
||||
if(settings.abiword == null && req.params.type != "html" && req.params.type != "txt" )
|
||||
if(settings.abiword == null &&
|
||||
["odt", "pdf", "doc"].indexOf(req.params.type) !== -1)
|
||||
{
|
||||
res.send("Abiword is not enabled at this Etherpad Lite instance. Set the path to Abiword in settings.json to enable this feature");
|
||||
return;
|
||||
|
@ -263,17 +307,12 @@ async.waterfall([
|
|||
exportHandler.doExport(req, res, req.params.pad, req.params.type);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
//handle import requests
|
||||
app.post('/p/:pad/import', function(req, res, next)
|
||||
{
|
||||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
return;
|
||||
}
|
||||
|
||||
goToPad(req, res, function() {
|
||||
//if abiword is disabled, skip handling this request
|
||||
if(settings.abiword == null)
|
||||
{
|
||||
|
@ -288,11 +327,13 @@ async.waterfall([
|
|||
importHandler.doImport(req, res, req.params.pad);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var apiLogger = log4js.getLogger("API");
|
||||
|
||||
//This is for making an api call, collecting all post information and passing it to the apiHandler
|
||||
var apiCaller = function(req, res, fields) {
|
||||
var apiCaller = function(req, res, fields)
|
||||
{
|
||||
res.header("Server", serverName);
|
||||
res.header("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
* Can be found in https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js
|
||||
*/
|
||||
|
||||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||
*
|
||||
|
|
344
node/utils/ExportDokuWiki.js
Normal file
344
node/utils/ExportDokuWiki.js
Normal file
|
@ -0,0 +1,344 @@
|
|||
/**
|
||||
* Copyright 2011 Adrian Lang
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var async = require("async");
|
||||
var Changeset = require("./Changeset");
|
||||
var padManager = require("../db/PadManager");
|
||||
|
||||
function getPadDokuWiki(pad, revNum, callback)
|
||||
{
|
||||
var atext = pad.atext;
|
||||
var dokuwiki;
|
||||
async.waterfall([
|
||||
// fetch revision atext
|
||||
|
||||
|
||||
function (callback)
|
||||
{
|
||||
if (revNum != undefined)
|
||||
{
|
||||
pad.getInternalRevisionAText(revNum, function (err, revisionAtext)
|
||||
{
|
||||
atext = revisionAtext;
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(null);
|
||||
}
|
||||
},
|
||||
|
||||
// convert atext to dokuwiki text
|
||||
|
||||
function (callback)
|
||||
{
|
||||
dokuwiki = getDokuWikiFromAtext(pad, atext);
|
||||
callback(null);
|
||||
}],
|
||||
// run final callback
|
||||
|
||||
|
||||
function (err)
|
||||
{
|
||||
callback(err, dokuwiki);
|
||||
});
|
||||
}
|
||||
|
||||
function getDokuWikiFromAtext(pad, atext)
|
||||
{
|
||||
var apool = pad.apool();
|
||||
var textLines = atext.text.slice(0, -1).split('\n');
|
||||
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
|
||||
|
||||
var tags = ['======', '=====', '**', '//', '__', 'del>'];
|
||||
var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough'];
|
||||
var anumMap = {};
|
||||
|
||||
props.forEach(function (propName, i)
|
||||
{
|
||||
var propTrueNum = apool.putAttrib([propName, true], true);
|
||||
if (propTrueNum >= 0)
|
||||
{
|
||||
anumMap[propTrueNum] = i;
|
||||
}
|
||||
});
|
||||
|
||||
function getLineDokuWiki(text, attribs)
|
||||
{
|
||||
var propVals = [false, false, false];
|
||||
var ENTER = 1;
|
||||
var STAY = 2;
|
||||
var LEAVE = 0;
|
||||
|
||||
// Use order of tags (b/i/u) as order of nesting, for simplicity
|
||||
// and decent nesting. For example,
|
||||
// <b>Just bold<b> <b><i>Bold and italics</i></b> <i>Just italics</i>
|
||||
// becomes
|
||||
// <b>Just bold <i>Bold and italics</i></b> <i>Just italics</i>
|
||||
var taker = Changeset.stringIterator(text);
|
||||
var assem = Changeset.stringAssembler();
|
||||
|
||||
function emitOpenTag(i)
|
||||
{
|
||||
if (tags[i].indexOf('>') !== -1) {
|
||||
assem.append('<');
|
||||
}
|
||||
assem.append(tags[i]);
|
||||
}
|
||||
|
||||
function emitCloseTag(i)
|
||||
{
|
||||
if (tags[i].indexOf('>') !== -1) {
|
||||
assem.append('</');
|
||||
}
|
||||
assem.append(tags[i]);
|
||||
}
|
||||
|
||||
var urls = _findURLs(text);
|
||||
|
||||
var idx = 0;
|
||||
|
||||
function processNextChars(numChars)
|
||||
{
|
||||
if (numChars <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + numChars));
|
||||
idx += numChars;
|
||||
|
||||
while (iter.hasNext())
|
||||
{
|
||||
var o = iter.next();
|
||||
var propChanged = false;
|
||||
Changeset.eachAttribNumber(o.attribs, function (a)
|
||||
{
|
||||
if (a in anumMap)
|
||||
{
|
||||
var i = anumMap[a]; // i = 0 => bold, etc.
|
||||
if (!propVals[i])
|
||||
{
|
||||
propVals[i] = ENTER;
|
||||
propChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
propVals[i] = STAY;
|
||||
}
|
||||
}
|
||||
});
|
||||
for (var i = 0; i < propVals.length; i++)
|
||||
{
|
||||
if (propVals[i] === true)
|
||||
{
|
||||
propVals[i] = LEAVE;
|
||||
propChanged = true;
|
||||
}
|
||||
else if (propVals[i] === STAY)
|
||||
{
|
||||
propVals[i] = true; // set it back
|
||||
}
|
||||
}
|
||||
// now each member of propVal is in {false,LEAVE,ENTER,true}
|
||||
// according to what happens at start of span
|
||||
if (propChanged)
|
||||
{
|
||||
// leaving bold (e.g.) also leaves italics, etc.
|
||||
var left = false;
|
||||
for (var i = 0; i < propVals.length; i++)
|
||||
{
|
||||
var v = propVals[i];
|
||||
if (!left)
|
||||
{
|
||||
if (v === LEAVE)
|
||||
{
|
||||
left = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v === true)
|
||||
{
|
||||
propVals[i] = STAY; // tag will be closed and re-opened
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = propVals.length - 1; i >= 0; i--)
|
||||
{
|
||||
if (propVals[i] === LEAVE)
|
||||
{
|
||||
emitCloseTag(i);
|
||||
propVals[i] = false;
|
||||
}
|
||||
else if (propVals[i] === STAY)
|
||||
{
|
||||
emitCloseTag(i);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < propVals.length; i++)
|
||||
{
|
||||
if (propVals[i] === ENTER || propVals[i] === STAY)
|
||||
{
|
||||
emitOpenTag(i);
|
||||
propVals[i] = true;
|
||||
}
|
||||
}
|
||||
// propVals is now all {true,false} again
|
||||
} // end if (propChanged)
|
||||
var chars = o.chars;
|
||||
if (o.lines)
|
||||
{
|
||||
chars--; // exclude newline at end of line, if present
|
||||
}
|
||||
var s = taker.take(chars);
|
||||
|
||||
assem.append(_escapeDokuWiki(s));
|
||||
} // end iteration over spans in line
|
||||
for (var i = propVals.length - 1; i >= 0; i--)
|
||||
{
|
||||
if (propVals[i])
|
||||
{
|
||||
emitCloseTag(i);
|
||||
propVals[i] = false;
|
||||
}
|
||||
}
|
||||
} // end processNextChars
|
||||
if (urls)
|
||||
{
|
||||
urls.forEach(function (urlData)
|
||||
{
|
||||
var startIndex = urlData[0];
|
||||
var url = urlData[1];
|
||||
var urlLength = url.length;
|
||||
processNextChars(startIndex - idx);
|
||||
assem.append('[[');
|
||||
|
||||
// Do not use processNextChars since a link does not contain syntax and
|
||||
// needs no escaping
|
||||
var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + urlLength));
|
||||
idx += urlLength;
|
||||
assem.append(taker.take(iter.next().chars));
|
||||
|
||||
assem.append(']]');
|
||||
});
|
||||
}
|
||||
processNextChars(text.length - idx);
|
||||
|
||||
return assem.toString() + "\n";
|
||||
} // end getLineDokuWiki
|
||||
var pieces = [];
|
||||
|
||||
for (var i = 0; i < textLines.length; i++)
|
||||
{
|
||||
var line = _analyzeLine(textLines[i], attribLines[i], apool);
|
||||
var lineContent = getLineDokuWiki(line.text, line.aline);
|
||||
|
||||
if (line.listLevel && lineContent)
|
||||
{
|
||||
pieces.push(new Array(line.listLevel + 1).join(' ') + '* ');
|
||||
}
|
||||
pieces.push(lineContent);
|
||||
}
|
||||
|
||||
return pieces.join('');
|
||||
}
|
||||
|
||||
function _analyzeLine(text, aline, apool)
|
||||
{
|
||||
var line = {};
|
||||
|
||||
// identify list
|
||||
var lineMarker = 0;
|
||||
line.listLevel = 0;
|
||||
if (aline)
|
||||
{
|
||||
var opIter = Changeset.opIterator(aline);
|
||||
if (opIter.hasNext())
|
||||
{
|
||||
var listType = Changeset.opAttributeValue(opIter.next(), 'list', apool);
|
||||
if (listType)
|
||||
{
|
||||
lineMarker = 1;
|
||||
listType = /([a-z]+)([12345678])/.exec(listType);
|
||||
if (listType)
|
||||
{
|
||||
line.listTypeName = listType[1];
|
||||
line.listLevel = Number(listType[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lineMarker)
|
||||
{
|
||||
line.text = text.substring(1);
|
||||
line.aline = Changeset.subattribution(aline, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
line.text = text;
|
||||
line.aline = aline;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
exports.getPadDokuWikiDocument = function (padId, revNum, callback)
|
||||
{
|
||||
padManager.getPad(padId, function (err, pad)
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
getPadDokuWiki(pad, revNum, callback);
|
||||
});
|
||||
}
|
||||
|
||||
function _escapeDokuWiki(s)
|
||||
{
|
||||
s = s.replace(/(\/\/|\*\*|__)/g, '%%$1%%');
|
||||
return s;
|
||||
}
|
||||
|
||||
// copied from ACE
|
||||
var _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
|
||||
var _REGEX_SPACE = /\s/;
|
||||
var _REGEX_URLCHAR = new RegExp('(' + /[-:@a-zA-Z0-9_.,~%+\/\\?=&#;()$]/.source + '|' + _REGEX_WORDCHAR.source + ')');
|
||||
var _REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|gopher|txmt):\/\/|mailto:)/.source + _REGEX_URLCHAR.source + '*(?![:.,;])' + _REGEX_URLCHAR.source, 'g');
|
||||
|
||||
// returns null if no URLs, or [[startIndex1, url1], [startIndex2, url2], ...]
|
||||
|
||||
|
||||
function _findURLs(text)
|
||||
{
|
||||
_REGEX_URL.lastIndex = 0;
|
||||
var urls = null;
|
||||
var execResult;
|
||||
while ((execResult = _REGEX_URL.exec(text)))
|
||||
{
|
||||
urls = (urls || []);
|
||||
var startIndex = execResult.index;
|
||||
var url = execResult[0];
|
||||
urls.push([startIndex, url]);
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
var async = require("async");
|
||||
var Changeset = require("./Changeset");
|
||||
var padManager = require("../db/PadManager");
|
||||
var ERR = require("async-stacktrace");
|
||||
|
||||
function getPadPlainText(pad, revNum)
|
||||
{
|
||||
|
@ -58,8 +59,9 @@ function getPadHTML(pad, revNum, callback)
|
|||
{
|
||||
pad.getInternalRevisionAText(revNum, function (err, revisionAtext)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
atext = revisionAtext;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -81,7 +83,8 @@ function getPadHTML(pad, revNum, callback)
|
|||
|
||||
function (err)
|
||||
{
|
||||
callback(err, html);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, html);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -459,11 +462,7 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
|||
{
|
||||
padManager.getPad(padId, function (err, pad)
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
var head =
|
||||
(noDocType ? '' : '<!doctype html>\n') +
|
||||
|
@ -488,7 +487,8 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
|||
|
||||
getPadHTML(pad, revNum, function (err, html)
|
||||
{
|
||||
callback(err, head + html + foot);
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, head + html + foot);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var jsdom = require('jsdom').jsdom;
|
||||
var jsdom = require('jsdom-nocontextifiy').jsdom;
|
||||
var log4js = require('log4js');
|
||||
|
||||
var Changeset = require("./Changeset");
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var settings = require('./Settings');
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
|
@ -33,7 +34,7 @@ var os = require('os');
|
|||
|
||||
var padJS = ["jquery.min.js", "pad_utils.js", "plugins.js", "undo-xpopup.js", "json2.js", "pad_cookie.js", "pad_editor.js", "pad_editbar.js", "pad_docbar.js", "pad_modals.js", "ace.js", "collab_client.js", "pad_userlist.js", "pad_impexp.js", "pad_savedrevs.js", "pad_connectionstatus.js", "pad2.js", "jquery-ui.js", "chat.js", "excanvas.js", "farbtastic.js"];
|
||||
|
||||
var timesliderJS = ["jquery.min.js", "plugins.js", "undo-xpopup.js", "json2.js", "colorutils.js", "draggable.js", "pad_utils.js", "pad_cookie.js", "pad_editor.js", "pad_editbar.js", "pad_docbar.js", "pad_modals.js", "easysync2_client.js", "domline_client.js", "linestylefilter_client.js", "cssmanager_client.js", "broadcast.js", "broadcast_slider.js", "broadcast_revisions.js"];
|
||||
var timesliderJS = ["jquery.min.js", "plugins.js", "undo-xpopup.js", "json2.js", "colorutils.js", "draggable.js", "pad_utils.js", "pad_cookie.js", "pad_editor.js", "pad_editbar.js", "pad_docbar.js", "pad_modals.js", "pad_impexp.js", "easysync2_client.js", "domline_client.js", "linestylefilter_client.js", "cssmanager_client.js", "broadcast.js", "broadcast_slider.js", "broadcast_revisions.js"];
|
||||
|
||||
/**
|
||||
* creates the minifed javascript for the given minified name
|
||||
|
@ -77,7 +78,7 @@ exports.minifyJS = function(req, res, jsFilename)
|
|||
//read the files in the folder
|
||||
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
|
||||
files.push(".");
|
||||
|
@ -88,7 +89,7 @@ exports.minifyJS = function(req, res, jsFilename)
|
|||
//get the stat data of this file
|
||||
fs.stat(path + "/" + filename, function(err, stats)
|
||||
{
|
||||
if(err) { callback(err); return; }
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//get the modification time
|
||||
var modificationTime = stats.mtime.getTime();
|
||||
|
@ -110,7 +111,11 @@ exports.minifyJS = function(req, res, jsFilename)
|
|||
//check the modification time of the minified js
|
||||
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
|
||||
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)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
fileValues[item] = data;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
},
|
||||
|
@ -161,6 +167,8 @@ exports.minifyJS = function(req, res, jsFilename)
|
|||
//read the included file
|
||||
fs.readFile(filename, "utf-8", function(err, data)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//compress the file
|
||||
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] + "'";
|
||||
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
}, function(err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//replace the include command with the include
|
||||
for(var i in embeds)
|
||||
{
|
||||
fileValues["ace.js"]=fileValues["ace.js"].replace(i, embeds[i]);
|
||||
}
|
||||
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//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)
|
||||
{
|
||||
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);
|
||||
});
|
||||
|
@ -242,7 +255,10 @@ exports.minifyJS = function(req, res, jsFilename)
|
|||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err && err != "stop") throw err;
|
||||
if(err && err != "stop")
|
||||
{
|
||||
if(ERR(err)) return;
|
||||
}
|
||||
|
||||
//check if gzip is supported by this browser
|
||||
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)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
fileValues[item] = data;
|
||||
callback(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//send all files together
|
||||
function(err)
|
||||
{
|
||||
if(err) throw err;
|
||||
if(ERR(err)) return;
|
||||
|
||||
for(var i=0;i<jsFiles.length;i++)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
|
||||
var fs = require("fs");
|
||||
var os = require("os");
|
||||
|
||||
/**
|
||||
* The IP ep-lite should listen to
|
||||
|
@ -68,6 +69,24 @@ exports.abiword = null;
|
|||
*/
|
||||
exports.loglevel = "INFO";
|
||||
|
||||
/**
|
||||
* Http basic auth, with "user:password" format
|
||||
*/
|
||||
exports.httpAuth = null;
|
||||
|
||||
//checks if abiword is avaiable
|
||||
exports.abiwordAvailable = function()
|
||||
{
|
||||
if(exports.abiword != null)
|
||||
{
|
||||
return os.type().indexOf("Windows") != -1 ? "withoutPDF" : "yes";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "no";
|
||||
}
|
||||
}
|
||||
|
||||
//read the settings sync
|
||||
var settingsStr = fs.readFileSync("../settings.json").toString();
|
||||
|
||||
|
|
17
node/utils/customError.js
Normal file
17
node/utils/customError.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
This helper modules allows us to create different type of errors we can throw
|
||||
*/
|
||||
function customError(message, errorName)
|
||||
{
|
||||
this.name = errorName || "Error";
|
||||
this.message = message;
|
||||
|
||||
var stackParts = new Error().stack.split("\n");
|
||||
stackParts.splice(0,2);
|
||||
stackParts.unshift(this.name + ": " + message);
|
||||
|
||||
this.stack = stackParts.join("\n");
|
||||
}
|
||||
customError.prototype = Error.prototype;
|
||||
|
||||
module.exports = customError;
|
|
@ -20,7 +20,8 @@
|
|||
"gzip" : "0.1.0",
|
||||
"formidable" : "1.0.7",
|
||||
"log4js" : "0.3.9",
|
||||
"jsdom" : "0.2.9"
|
||||
"jsdom-nocontextifiy" : "0.2.10",
|
||||
"async-stacktrace" : "0.0.2"
|
||||
},
|
||||
"version" : "1.0.0"
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
Abiword is needed to enable the import/export of pads*/
|
||||
"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 */
|
||||
"loglevel": "INFO"
|
||||
}
|
||||
|
|
|
@ -472,12 +472,10 @@ table#otheruserstable { display: none; }
|
|||
background: url(../../static/img/connectingbar.gif) no-repeat center 60px;
|
||||
height: 100px;
|
||||
}
|
||||
.modaldialog.cboxreconnecting {
|
||||
background: #fed;
|
||||
}
|
||||
.modaldialog.cboxreconnecting,
|
||||
.modaldialog.cboxconnecting,
|
||||
.modaldialog.cboxdisconnected {
|
||||
background: #fdd;
|
||||
background: #8FCDE0;
|
||||
}
|
||||
.cboxdisconnected #connectionboxinner div { display: none; }
|
||||
.cboxdisconnected_userdup #connectionboxinner #disconnected_userdup { display: block; }
|
||||
|
@ -1005,7 +1003,7 @@ position: relative;
|
|||
padding: 10px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
height:170px;
|
||||
height:190px;
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
@ -1034,7 +1032,7 @@ position: relative;
|
|||
|
||||
#importexportline{
|
||||
border: dotted 1px;
|
||||
height: 165px;
|
||||
height: 185px;
|
||||
position:absolute;
|
||||
width:0px;
|
||||
left:260px;
|
||||
|
@ -1070,6 +1068,10 @@ position: relative;
|
|||
background-position: 2px -49px;
|
||||
}
|
||||
|
||||
#exportdokuwiki{
|
||||
background-position: 2px -144px;
|
||||
}
|
||||
|
||||
#export a{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
@ -1146,17 +1148,103 @@ width:33px !important;
|
|||
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) {
|
||||
#editbar ul li {
|
||||
padding: 4px 1px;
|
||||
}
|
||||
}
|
||||
|
||||
#embedreadonlyqr{
|
||||
padding-top:20px;
|
||||
margin-left:100px;
|
||||
@media only screen and (min-device-width: 320px) and (max-device-width: 720px) {
|
||||
#editbar ul li {
|
||||
padding: 4px 3px;
|
||||
}
|
||||
|
||||
#qrcode{
|
||||
margin-left:10px;
|
||||
#editbar ul#menu_right > li {
|
||||
padding: 4px 8px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
#chaticon {
|
||||
opacity: .8;
|
||||
}
|
||||
#users {
|
||||
right: 4px;
|
||||
}
|
||||
#mycolorpicker {
|
||||
left: -72px; /* #mycolorpicker:width - #users:width */
|
||||
}
|
||||
#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;
|
||||
}
|
||||
}
|
||||
.rtl{
|
||||
direction:RTL;
|
||||
}
|
||||
|
|
|
@ -195,6 +195,11 @@ float:right;
|
|||
color: #222;
|
||||
}
|
||||
|
||||
#importexport{
|
||||
top:103px;
|
||||
width:185px;
|
||||
}
|
||||
|
||||
ul { margin-left: 1.5em; }
|
||||
ul ul { margin-left: 0 !important; }
|
||||
ul.list-bullet1 { margin-left: 1.5em; }
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.6 KiB |
|
@ -1,6 +1,8 @@
|
|||
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Etherpad Lite</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<style>
|
||||
*{ margin:0;padding:0; }
|
||||
body {
|
||||
|
@ -13,13 +15,12 @@
|
|||
background: -ms-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
||||
background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
||||
overflow-x: hidden;
|
||||
border-top: 8px solid rgba(51,51,51,.8)
|
||||
border-top: 8px solid rgba(51,51,51,.8);
|
||||
}
|
||||
#container {
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
border-top: 1px solid #999;
|
||||
margin-top: 160px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
background: #eee;
|
||||
|
@ -28,7 +29,7 @@
|
|||
background: -ms-linear-gradient(#fff,#ccc);
|
||||
background: -o-linear-gradient(#fff,#ccc);
|
||||
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 {
|
||||
margin: 0 auto;
|
||||
|
@ -45,7 +46,7 @@
|
|||
background: -moz-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);
|
||||
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 {
|
||||
cursor: pointer;
|
||||
|
@ -53,21 +54,21 @@
|
|||
background: -webkit-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: -o-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747)
|
||||
background: -o-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
|
||||
}
|
||||
#button:active {
|
||||
box-shadow: inset 0 1px 12px rgba(0,0,0,0.9);
|
||||
background: #444
|
||||
background: #444;
|
||||
}
|
||||
#label {
|
||||
text-align: left;
|
||||
margin: 0 auto;
|
||||
width: 300px
|
||||
width: 300px;
|
||||
}
|
||||
input {
|
||||
vertical-align: middle;
|
||||
font-weight: bold;
|
||||
font-size: 15px
|
||||
font-size: 15px;
|
||||
}
|
||||
input[type="text"] {
|
||||
width: 243px;
|
||||
|
@ -76,23 +77,43 @@
|
|||
border: 1px solid #bbb;
|
||||
outline: none;
|
||||
border-radius: 3px;
|
||||
text-shadow: 0 0 1px #fff
|
||||
text-shadow: 0 0 1px #fff;
|
||||
}
|
||||
input[type="submit"] {
|
||||
width: 45px;
|
||||
margin-left: -50px;
|
||||
padding: 8px
|
||||
padding: 8px;
|
||||
}
|
||||
input[type="submit"]::-moz-focus-inner { border: 0 }
|
||||
@-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>
|
||||
<body onload="document.mainform.padname.focus();">
|
||||
<link href="static/custom/index.css" rel="stylesheet">
|
||||
<script src="static/custom/index.js"></script>
|
||||
<div id="container">
|
||||
<div id="button" onclick="go2Random()">New Pad</div><br><div id="label">or create/open a Pad with the name</div>
|
||||
<form action="#" name="mainform" onsubmit="go2Name();return false;">
|
||||
<input type="text" name="padname" id="padname" autofocus>
|
||||
<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="#" onsubmit="go2Name();return false;">
|
||||
<input type="text" id="padname" autofocus>
|
||||
<input type="submit" value="OK">
|
||||
</form>
|
||||
</div>
|
||||
|
@ -124,5 +145,4 @@
|
|||
//start the costum js
|
||||
if(typeof costumStart == "function") costumStart();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
@ -80,6 +86,11 @@ function OUTER(gscope)
|
|||
var hasLineNumbers = true;
|
||||
var isStyled = true;
|
||||
|
||||
// check for mobile os presence
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
var isAndroid = ua.indexOf("android") > -1;
|
||||
var isMobileSafari = ua.indexOf("mobile") > -1;
|
||||
|
||||
// space around the innermost iframe element
|
||||
var iframePadLeft = MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT;
|
||||
var iframePadTop = EDIT_BODY_PADDING_TOP;
|
||||
|
@ -1099,6 +1110,8 @@ function OUTER(gscope)
|
|||
else if (k == "showslinenumbers")
|
||||
{
|
||||
hasLineNumbers = !! value;
|
||||
// disable line numbers on mobile devices
|
||||
if(isAndroid || isMobileSafari) hasLineNumbers = false;
|
||||
setClassPresence(sideDiv, "sidedivhidden", !hasLineNumbers);
|
||||
fixView();
|
||||
}
|
||||
|
@ -1127,6 +1140,10 @@ function OUTER(gscope)
|
|||
{
|
||||
setTextSize(value);
|
||||
}
|
||||
else if (k == 'rtlistrue')
|
||||
{
|
||||
setClassPresence(root, "rtl", !! value);
|
||||
}
|
||||
}
|
||||
|
||||
editorInfo.ace_setBaseText = function(txt)
|
||||
|
@ -4069,8 +4086,6 @@ function OUTER(gscope)
|
|||
catch (e)
|
||||
{}
|
||||
if (!origSelectionRange) return false;
|
||||
var selectionParent = origSelectionRange.parentElement();
|
||||
if (selectionParent.ownerDocument != doc) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -5779,31 +5794,17 @@ function OUTER(gscope)
|
|||
{
|
||||
var newNumLines = rep.lines.length();
|
||||
if (newNumLines < 1) newNumLines = 1;
|
||||
if (newNumLines != lineNumbersShown)
|
||||
{
|
||||
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--;
|
||||
}
|
||||
}
|
||||
|
||||
//update height of all current line numbers
|
||||
if (currentCallStack && currentCallStack.domClean)
|
||||
{
|
||||
var a = sideDivInner.firstChild;
|
||||
var b = doc.body.firstChild;
|
||||
var n = 0;
|
||||
while (a && b)
|
||||
{
|
||||
if(n > lineNumbersShown) //all updated, break
|
||||
break;
|
||||
|
||||
var h = (b.clientHeight || b.offsetHeight);
|
||||
if (b.nextSibling)
|
||||
{
|
||||
|
@ -5817,10 +5818,42 @@ function OUTER(gscope)
|
|||
if (h)
|
||||
{
|
||||
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;
|
||||
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--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||
*
|
||||
|
@ -16,21 +22,33 @@
|
|||
|
||||
var chat = (function()
|
||||
{
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
var isAndroid = ua.indexOf("android") > -1;
|
||||
var isMobileSafari = ua.indexOf("mobile") > -1;
|
||||
var bottomMargin = "0px";
|
||||
var sDuration = 500;
|
||||
var hDuration = 750;
|
||||
var chatMentions = 0;
|
||||
var title = document.title;
|
||||
if (isAndroid || isMobileSafari){
|
||||
sDuration = 0;
|
||||
hDuration = 0;
|
||||
}
|
||||
var self = {
|
||||
show: function ()
|
||||
{
|
||||
$("#chaticon").hide("slide", {
|
||||
direction: "down"
|
||||
}, 500, function ()
|
||||
}, hDuration, function ()
|
||||
{
|
||||
$("#chatbox").show("slide", {
|
||||
direction: "down"
|
||||
}, 750, self.scrollDown);
|
||||
}, sDuration, self.scrollDown);
|
||||
$("#chatbox").resizable(
|
||||
{
|
||||
handles: 'nw',
|
||||
minHeight: 40,
|
||||
minWidth: 80,
|
||||
start: function (event, ui)
|
||||
{
|
||||
$("#focusprotector").show();
|
||||
|
@ -39,7 +57,10 @@ var chat = (function()
|
|||
{
|
||||
$("#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();
|
||||
}
|
||||
|
@ -51,9 +72,9 @@ var chat = (function()
|
|||
hide: function ()
|
||||
{
|
||||
$("#chatcounter").text("0");
|
||||
$("#chatbox").hide("slide", { direction: "down" }, 750, function()
|
||||
$("#chatbox").hide("slide", { direction: "down" }, sDuration, function()
|
||||
{
|
||||
$("#chaticon").show("slide", { direction: "down" }, 500);
|
||||
$("#chaticon").show("slide", { direction: "down" }, hDuration);
|
||||
});
|
||||
},
|
||||
scrollDown: function()
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// DO NOT EDIT THIS FILE, edit infrastructure/ace/www/colorutils.js
|
||||
// THIS FILE IS ALSO SERVED AS CLIENT-SIDE JS
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.contentcollector
|
||||
// %APPJET%: import("etherpad.collab.ace.easysync2.Changeset");
|
||||
// %APPJET%: import("etherpad.admin.plugins");
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// DO NOT EDIT THIS FILE, edit infrastructure/ace/www/cssmanager.js
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.domline
|
||||
// %APPJET%: import("etherpad.admin.plugins");
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// DO NOT EDIT THIS FILE, edit infrastructure/ace/www/domline.js
|
||||
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.domline
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.easysync2
|
||||
// %APPJET%: jimport("com.etherpad.Easysync2Support");
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// DO NOT EDIT THIS FILE, edit infrastructure/ace/www/easysync2.js
|
||||
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.easysync2
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.linestylefilter
|
||||
// %APPJET%: import("etherpad.collab.ace.easysync2.Changeset");
|
||||
// %APPJET%: import("etherpad.admin.plugins");
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
// DO NOT EDIT THIS FILE, edit infrastructure/ace/www/linestylefilter.js
|
||||
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.linestylefilter
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||
*
|
||||
|
@ -21,6 +27,8 @@ var LineNumbersDisabled = false;
|
|||
var noColors = false;
|
||||
var useMonospaceFontGlobal = false;
|
||||
var globalUserName = false;
|
||||
var hideQRCode = false;
|
||||
var rtlIsTrue = false;
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
|
@ -86,12 +94,15 @@ function getParams()
|
|||
var showLineNumbers = params["showLineNumbers"];
|
||||
var useMonospaceFont = params["useMonospaceFont"];
|
||||
var IsnoColors = params["noColors"];
|
||||
var hideQRCode = params["hideQRCode"];
|
||||
var rtl = params["rtl"];
|
||||
|
||||
if(IsnoColors)
|
||||
{
|
||||
if(IsnoColors == "true")
|
||||
{
|
||||
noColors = true;
|
||||
$('#clearAuthorship').hide();
|
||||
}
|
||||
}
|
||||
if(showControls)
|
||||
|
@ -102,7 +113,6 @@ function getParams()
|
|||
$('#editorcontainer').css({"top":"0px"});
|
||||
}
|
||||
}
|
||||
|
||||
if(showChat)
|
||||
{
|
||||
if(showChat == "false")
|
||||
|
@ -110,7 +120,6 @@ function getParams()
|
|||
$('#chaticon').hide();
|
||||
}
|
||||
}
|
||||
|
||||
if(showLineNumbers)
|
||||
{
|
||||
if(showLineNumbers == "false")
|
||||
|
@ -118,7 +127,6 @@ function getParams()
|
|||
LineNumbersDisabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(useMonospaceFont)
|
||||
{
|
||||
if(useMonospaceFont == "true")
|
||||
|
@ -126,13 +134,22 @@ function getParams()
|
|||
useMonospaceFontGlobal = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
globalUserName = unescape(userName);
|
||||
}
|
||||
if(hideQRCode)
|
||||
{
|
||||
$('#qrcode').hide();
|
||||
}
|
||||
if(rtl)
|
||||
{
|
||||
if(rtl == "true")
|
||||
{
|
||||
rtlIsTrue = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getUrlVars()
|
||||
|
@ -177,7 +194,7 @@ function handshake()
|
|||
padId = decodeURIComponent(padId); // unescape neccesary due to Safari and Opera interpretation of spaces
|
||||
|
||||
if(!isReconnect)
|
||||
document.title = document.title + " | " + padId;
|
||||
document.title = document.title + " | " + padId.replace(/_+/g, ' ');
|
||||
|
||||
var token = readCookie("token");
|
||||
if (token == null)
|
||||
|
@ -292,6 +309,11 @@ function handshake()
|
|||
pad.changeViewOption('noColors', true);
|
||||
}
|
||||
|
||||
if (rtlIsTrue == true)
|
||||
{
|
||||
pad.changeViewOption('rtl', true);
|
||||
}
|
||||
|
||||
// If the Monospacefont value is set to true then change it to monospace.
|
||||
if (useMonospaceFontGlobal == true)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
@ -151,7 +157,7 @@ var padeditbar = (function()
|
|||
}, cmd, true);
|
||||
}
|
||||
}
|
||||
padeditor.ace.focus();
|
||||
if(padeditor.ace) padeditor.ace.focus();
|
||||
},
|
||||
toogleDropDown: function(moduleName)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
@ -89,6 +95,7 @@ var padeditor = (function()
|
|||
|
||||
self.ace.setProperty("showsauthorcolors", noColors);
|
||||
|
||||
self.ace.setProperty("rtlIsTrue", rtlIsTrue);
|
||||
},
|
||||
initViewZoom: function()
|
||||
{
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
@ -230,10 +236,16 @@ var padimpexp = (function()
|
|||
var self = {
|
||||
init: function()
|
||||
{
|
||||
//get /p/padname
|
||||
var pad_root_path = new RegExp(/.*\/p\/[^\/]+/).exec(document.location.pathname)
|
||||
//get http://example.com/p/padname
|
||||
var pad_root_url = document.location.href.replace(document.location.pathname, pad_root_path)
|
||||
|
||||
// build the export links
|
||||
$("#exporthtmla").attr("href", document.location.pathname + "/export/html");
|
||||
$("#exportplaina").attr("href", document.location.pathname + "/export/txt");
|
||||
$("#exportwordlea").attr("href", document.location.pathname + "/export/wordle");
|
||||
$("#exporthtmla").attr("href", pad_root_path + "/export/html");
|
||||
$("#exportplaina").attr("href", pad_root_path + "/export/txt");
|
||||
$("#exportwordlea").attr("href", pad_root_path + "/export/wordle");
|
||||
$("#exportdokuwikia").attr("href", pad_root_path + "/export/dokuwiki");
|
||||
|
||||
//hide stuff thats not avaible if abiword is disabled
|
||||
if(clientVars.abiwordAvailable == "no")
|
||||
|
@ -241,29 +253,29 @@ var padimpexp = (function()
|
|||
$("#exportworda").remove();
|
||||
$("#exportpdfa").remove();
|
||||
$("#exportopena").remove();
|
||||
$("#importexport").css({"height":"95px"});
|
||||
$("#importexportline").css({"height":"95px"});
|
||||
$("#importexport").css({"height":"115px"});
|
||||
$("#importexportline").css({"height":"115px"});
|
||||
$("#import").html("Import is not available");
|
||||
}
|
||||
else if(clientVars.abiwordAvailable == "withoutPDF")
|
||||
{
|
||||
$("#exportpdfa").remove();
|
||||
|
||||
$("#exportworda").attr("href", document.location.pathname + "/export/doc");
|
||||
$("#exportopena").attr("href", document.location.pathname + "/export/odt");
|
||||
$("#exportworda").attr("href", pad_root_path + "/export/doc");
|
||||
$("#exportopena").attr("href", pad_root_path + "/export/odt");
|
||||
|
||||
$("#importexport").css({"height":"142px"});
|
||||
$("#importexportline").css({"height":"142px"});
|
||||
|
||||
$("#importform").get(0).setAttribute('action', document.location.href + "/import");
|
||||
$("#importform").attr('action', pad_root_url + "/import");
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#exportworda").attr("href", document.location.pathname + "/export/doc");
|
||||
$("#exportpdfa").attr("href", document.location.pathname + "/export/pdf");
|
||||
$("#exportopena").attr("href", document.location.pathname + "/export/odt");
|
||||
$("#exportworda").attr("href", pad_root_path + "/export/doc");
|
||||
$("#exportpdfa").attr("href", pad_root_path + "/export/pdf");
|
||||
$("#exportopena").attr("href", pad_root_path + "/export/odt");
|
||||
|
||||
$("#importform").get(0).setAttribute('action', document.location.pathname + "/import");
|
||||
$("#importform").attr('action', pad_root_path + "/import");
|
||||
}
|
||||
|
||||
$("#impexp-close").click(function()
|
||||
|
@ -301,7 +313,7 @@ var padimpexp = (function()
|
|||
},
|
||||
export2Wordle: function()
|
||||
{
|
||||
var padUrl = document.location.href + "/export/txt";
|
||||
var padUrl = $('#exportwordlea').attr('href').replace(/\/wordle$/, '/txt')
|
||||
|
||||
$.get(padUrl, function(data)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
@ -711,8 +717,15 @@ var paduserlist = (function()
|
|||
}
|
||||
|
||||
$("#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});
|
||||
}
|
||||
}
|
||||
};
|
||||
return self;
|
||||
}());
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
plugins = {
|
||||
callHook: function(hookName, args)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<title>Etherpad Lite</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<!-- CSS -->
|
||||
<link href="../static/css/pad.css" rel="stylesheet">
|
||||
<!-- javascript -->
|
||||
<script type="text/javascript">
|
||||
// <![CDATA[
|
||||
var clientVars = {}; // ]]>
|
||||
var clientVars = {};
|
||||
// ]]>
|
||||
</script>
|
||||
<script src="../socket.io/socket.io.js"></script>
|
||||
<script src="../minified/pad.js"></script>
|
||||
|
@ -23,60 +25,60 @@
|
|||
<div id="editbar">
|
||||
|
||||
<ul id="menu_left">
|
||||
<li onClick="window.pad&&pad.editbarClick('bold');return false" >
|
||||
<li onClick="window.pad&&pad.editbarClick('bold');return false" >
|
||||
<a title="Bold (ctrl-B)">
|
||||
<div class="buttonicon" style="background-position:0px -116px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('italic'); return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('italic'); return false;" >
|
||||
<a title="Italics (ctrl-I)">
|
||||
<div class="buttonicon" style="background-position:0px 0px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('underline');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('underline');return false;" >
|
||||
<a title="Underline (ctrl-U)">
|
||||
<div class="buttonicon" style="background-position:0px -236px;margin-top:1px;"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('strikethrough');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('strikethrough');return false;" >
|
||||
<a title="Strikethrough">
|
||||
<div class="buttonicon" style="background-position:0px -200px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="separator"></li>
|
||||
<li onClick="window.pad&&pad.editbarClick('insertorderedlist');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('insertorderedlist');return false;" >
|
||||
<a title="Toggle Ordered List">
|
||||
<div class="buttonicon" style="background-position:0px -436px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('insertunorderedlist');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('insertunorderedlist');return false;" >
|
||||
<a title="Toggle Bullet List">
|
||||
<div class="buttonicon" style="background-position:0px -34px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('indent');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('indent');return false;" >
|
||||
<a title="Indent">
|
||||
<div class="buttonicon" style="background-position:0px -52px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('outdent');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('outdent');return false;" >
|
||||
<a title="Unindent">
|
||||
<div class="buttonicon" style="background-position:0px -134px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="separator"></li>
|
||||
<li onClick="window.pad&&pad.editbarClick('undo');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('undo');return false;" >
|
||||
<a title="Undo (ctrl-Z)">
|
||||
<div class="buttonicon" style="background-position:0px -255px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('redo');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('redo');return false;" >
|
||||
<a title="Redo (ctrl-Y)">
|
||||
<div class="buttonicon" style="background-position:0px -166px"></div>
|
||||
</a>
|
||||
</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">
|
||||
<div class="buttonicon" style="background-position:0px -86px"></div>
|
||||
</a>
|
||||
|
@ -85,12 +87,12 @@
|
|||
|
||||
<ul id="menu_right">
|
||||
|
||||
<li onClick="window.pad&&pad.editbarClick('import_export');return false;">
|
||||
<li onClick="window.pad&&pad.editbarClick('import_export');return false;">
|
||||
<a id="exportlink" title="Import/Export from/to different document formats">
|
||||
<div class="buttonicon" style="background-position:0px -68px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('embed');return false;" >
|
||||
<li onClick="window.pad&&pad.editbarClick('embed');return false;" >
|
||||
<a id="embedlink" title="Share and Embed this pad">
|
||||
<div class="buttonicon" style="background-position:0px -18px"></div>
|
||||
</a>
|
||||
|
@ -101,7 +103,7 @@
|
|||
<div class="buttonicon" style="background-position:0px -218px"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="usericon" onClick="window.pad&&pad.editbarClick('showusers');return false;" >
|
||||
<li id="usericon" onClick="window.pad&&pad.editbarClick('showusers');return false;" >
|
||||
<a title="Show connected users">
|
||||
<div class="buttonicon" id="usericonback" style="background-position:0px -184px;display:inline-block;"></div>
|
||||
<span id="online_count">1</span>
|
||||
|
@ -208,9 +210,10 @@
|
|||
<a id="exportworda" target="_blank" class="exportlink"><div class="exporttype" id="exportword">Microsoft Word</div></a>
|
||||
<a id="exportpdfa" target="_blank" class="exportlink"><div class="exporttype" id="exportpdf">PDF</div></a>
|
||||
<a id="exportopena" target="_blank" class="exportlink"><div class="exporttype" id="exportopen">OpenDocument</div></a>
|
||||
<a id="exportdokuwikia" target="_blank" class="exportlink"><div class="exporttype" id="exportdokuwiki">DokuWiki text</div></a>
|
||||
<a id="exportwordlea" target="_blank" onClick="padimpexp.export2Wordle();return false;" class="exportlink"><div class="exporttype" id="exportwordle">Wordle</div></a>
|
||||
<form id="wordlepost" name="wall" action="http://wordle.net/advanced" method="POST" style="margin-left:0px;">
|
||||
<div id="hidetext" style=""><textarea id="text" name="text" id="text" style="display:none;">Coming soon!</textarea></div>
|
||||
<div id="hidetext" style=""><textarea id="text" name="text" style="display:none;">Coming soon!</textarea></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -230,7 +233,7 @@
|
|||
</div><br/>
|
||||
<div id="qrcode">
|
||||
<label for="embedreadonlyqr">QR code:</label><br/>
|
||||
<img id="embedreadonlyqr">
|
||||
<div id="qr_center"><img id="embedreadonlyqr"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
return "t." + randomstring;
|
||||
}
|
||||
|
||||
var socket, token, padId;
|
||||
var socket, token, padId, export_links;
|
||||
|
||||
$(document).ready(function ()
|
||||
{
|
||||
|
@ -65,7 +65,7 @@
|
|||
padId = decodeURIComponent(urlParts[urlParts.length-2]);
|
||||
|
||||
//set the title
|
||||
document.title = document.title + " | " + padId;
|
||||
document.title = document.title + " | " + padId.replace(/_+/g, ' ');
|
||||
|
||||
//ensure we have a token
|
||||
token = readCookie("token");
|
||||
|
@ -110,6 +110,9 @@
|
|||
$("body").html("<h2>You have no permission to access this pad</h2>")
|
||||
}
|
||||
});
|
||||
|
||||
//get all the export links
|
||||
export_links = $('#export > .exportlink')
|
||||
});
|
||||
|
||||
//sends a message over the socket
|
||||
|
@ -142,6 +145,19 @@
|
|||
loadBroadcastRevisionsJS();
|
||||
loadBroadcastJS();
|
||||
|
||||
//initialize export ui
|
||||
padimpexp.init();
|
||||
|
||||
//change export urls when the slider moves
|
||||
var export_rev_regex = /(\/\d+)?\/export/
|
||||
BroadcastSlider.onSlider(function(revno)
|
||||
{
|
||||
export_links.each(function()
|
||||
{
|
||||
this.setAttribute('href', this.href.replace(export_rev_regex, '/' + revno + '/export'));
|
||||
});
|
||||
});
|
||||
|
||||
//fire all start functions of these scripts, formerly fired with window.load
|
||||
for(var i=0;i < fireWhenAllScriptsAreLoaded.length;i++)
|
||||
{
|
||||
|
@ -269,6 +285,13 @@
|
|||
|
||||
<div id="editbarright" class="editbarright">
|
||||
<!-- termporary place holder-->
|
||||
<ul>
|
||||
<li onClick="window.padeditbar.toolbarClick('import_export');return false;">
|
||||
<a id="exportlink" title="Export to different document formats">
|
||||
<div class="buttonicon" style="background-position:0px -68px"></div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a id = "returnbutton">Return to pad</a>
|
||||
<script>
|
||||
if(document.referrer.length > 0 && document.referrer.substring(document.referrer.lastIndexOf("/")-1,document.referrer.lastIndexOf("/")) === "p") {
|
||||
|
@ -320,6 +343,24 @@
|
|||
</div>
|
||||
|
||||
<div id="mainmodals"></div>
|
||||
|
||||
<!-- export code -->
|
||||
<div id="importexport">
|
||||
|
||||
<div id="export">
|
||||
Export current version as:
|
||||
<a id="exporthtmla" target="_blank" class="exportlink"><div class="exporttype" id="exporthtml">HTML</div></a>
|
||||
<a id="exportplaina" target="_blank" class="exportlink"><div class="exporttype" id="exportplain">Plain text</div></a>
|
||||
<a id="exportworda" target="_blank" class="exportlink"><div class="exporttype" id="exportword">Microsoft Word</div></a>
|
||||
<a id="exportpdfa" target="_blank" class="exportlink"><div class="exporttype" id="exportpdf">PDF</div></a>
|
||||
<a id="exportopena" target="_blank" class="exportlink"><div class="exporttype" id="exportopen">OpenDocument</div></a>
|
||||
<a id="exportdokuwikia" target="_blank" class="exportlink"><div class="exporttype" id="exportdokuwiki">DokuWiki text</div></a>
|
||||
<a id="exportwordlea" target="_blank" onClick="padimpexp.export2Wordle();return false;" class="exportlink"><div class="exporttype" id="exportwordle">Wordle</div></a>
|
||||
<form id="wordlepost" name="wall" action="http://wordle.net/advanced" method="POST" style="margin-left:0px;">
|
||||
<div id="hidetext" style=""><textarea id="text" name="text" id="text" style="display:none;">Coming soon!</textarea></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue