Merge branch 'develop' of https://github.com/Pita/etherpad-lite into pita-plugin
|
@ -10,4 +10,7 @@ var/dirty.db
|
|||
bin/convertSettings.json
|
||||
*~
|
||||
*.patch
|
||||
src/static/js/jquery.js
|
||||
src/static/js/prefixfree.js
|
||||
npm-debug.log
|
||||
*.DS_Store
|
|
@ -0,0 +1,7 @@
|
|||
.git*
|
||||
docs/
|
||||
examples/
|
||||
support/
|
||||
test/
|
||||
testing.js
|
||||
.DS_Store
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"parts": [
|
||||
{
|
||||
"name": "somepart",
|
||||
"pre": [],
|
||||
"post": ["ep_onemoreplugin/partone"]
|
||||
},
|
||||
{
|
||||
"name": "partlast",
|
||||
"pre": ["ep_fintest/otherpart"],
|
||||
"post": [],
|
||||
"hooks": {
|
||||
"somehookname": "ep_fintest/partlast:somehook"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "partfirst",
|
||||
"pre": [],
|
||||
"post": ["ep_onemoreplugin/somepart"]
|
||||
},
|
||||
{
|
||||
"name": "otherpart",
|
||||
"pre": ["ep_fintest/somepart", "ep_otherplugin/main"],
|
||||
"post": [],
|
||||
"hooks": {
|
||||
"somehookname": "ep_fintest/otherpart:somehook",
|
||||
"morehook": "ep_fintest/otherpart:morehook",
|
||||
"expressCreateServer": "ep_fintest/otherpart:expressServer"
|
||||
},
|
||||
"client_hooks": {
|
||||
"somehookname": "ep_fintest/static/js/test:bar"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
test = require("ep_fintest/static/js/test.js");
|
||||
console.log("FOOO:", test.foo);
|
||||
|
||||
exports.somehook = function (hook_name, args, cb) {
|
||||
return cb(["otherpart:somehook was here"]);
|
||||
}
|
||||
|
||||
exports.morehook = function (hook_name, args, cb) {
|
||||
return cb(["otherpart:morehook was here"]);
|
||||
}
|
||||
|
||||
exports.expressServer = function (hook_name, args, cb) {
|
||||
args.app.get('/otherpart', function(req, res) {
|
||||
res.send("<em>Abra cadabra</em>");
|
||||
});
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "ep_fintest",
|
||||
"description": "A test plugin",
|
||||
"version": "0.0.1",
|
||||
"author": "RedHog (Egil Moeller) <egil.moller@freecode.no>",
|
||||
"contributors": [],
|
||||
"dependencies": {},
|
||||
"engines": { "node": ">= 0.4.1 < 0.7.0" }
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
exports.somehook = function (hook_name, args, cb) {
|
||||
return cb(["partlast:somehook was here"]);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
exports.foo = 42;
|
||||
|
||||
exports.bar = function (hook_name, args, cb) {
|
||||
return cb(["FOOOO"]);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<em>Test bla bla</em>
|
|
@ -15,8 +15,8 @@ var log4js = require("log4js");
|
|||
log4js.setGlobalLogLevel("INFO");
|
||||
var async = require("async");
|
||||
var db = require('../node/db/DB');
|
||||
var CommonCode = require('../node/utils/common_code');
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var padManager;
|
||||
|
||||
async.series([
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
var CommonCode = require('../node/utils/common_code');
|
||||
|
||||
var startTime = new Date().getTime();
|
||||
var fs = require("fs");
|
||||
var ueberDB = require("ueberDB");
|
||||
var mysql = require("mysql");
|
||||
var async = require("async");
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
var randomString = CommonCode.require('/pad_utils').randomString;
|
||||
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||
var AttributePoolFactory = require("ep_etherpad-lite/static/js/AttributePoolFactory");
|
||||
|
||||
var settingsFile = process.argv[2];
|
||||
var sqlOutputFile = process.argv[3];
|
||||
|
|
|
@ -22,8 +22,7 @@ node-inspector &
|
|||
|
||||
echo "If you are new to node-inspector, take a look at this video: http://youtu.be/AOnK3NVnxL8"
|
||||
|
||||
cd "node"
|
||||
node --debug server.js
|
||||
node --debug node_modules/ep_etherpad-lite/node/server.js $*
|
||||
|
||||
#kill node-inspector before ending
|
||||
kill $!
|
||||
|
|
|
@ -55,7 +55,13 @@ if [ ! -f $settings ]; then
|
|||
fi
|
||||
|
||||
echo "Ensure that all dependencies are up to date..."
|
||||
npm install || {
|
||||
(
|
||||
mkdir -p node_modules
|
||||
cd node_modules
|
||||
[ -e ep_etherpad-lite ] || ln -s ../src ep_etherpad-lite
|
||||
cd ep_etherpad-lite
|
||||
npm install
|
||||
) || {
|
||||
rm -rf node_modules
|
||||
exit 1
|
||||
}
|
||||
|
@ -63,8 +69,8 @@ npm install || {
|
|||
echo "Ensure jQuery is downloaded and up to date..."
|
||||
DOWNLOAD_JQUERY="true"
|
||||
NEEDED_VERSION="1.7.1"
|
||||
if [ -f "static/js/jquery.js" ]; then
|
||||
VERSION=$(cat static/js/jquery.js | head -n 3 | grep -o "v[0-9]\.[0-9]\(\.[0-9]\)\?");
|
||||
if [ -f "src/static/js/jquery.js" ]; then
|
||||
VERSION=$(cat src/static/js/jquery.js | head -n 3 | grep -o "v[0-9]\.[0-9]\(\.[0-9]\)\?");
|
||||
|
||||
if [ ${VERSION#v} = $NEEDED_VERSION ]; then
|
||||
DOWNLOAD_JQUERY="false"
|
||||
|
@ -72,14 +78,14 @@ if [ -f "static/js/jquery.js" ]; then
|
|||
fi
|
||||
|
||||
if [ $DOWNLOAD_JQUERY = "true" ]; then
|
||||
curl -lo static/js/jquery.js http://code.jquery.com/jquery-$NEEDED_VERSION.js || exit 1
|
||||
curl -lo src/static/js/jquery.js http://code.jquery.com/jquery-$NEEDED_VERSION.js || exit 1
|
||||
fi
|
||||
|
||||
echo "Ensure prefixfree is downloaded and up to date..."
|
||||
DOWNLOAD_PREFIXFREE="true"
|
||||
NEEDED_VERSION="1.0.4"
|
||||
if [ -f "static/js/prefixfree.js" ]; then
|
||||
VERSION=$(cat static/js/prefixfree.js | grep "PrefixFree" | grep -o "[0-9].[0-9].[0-9]");
|
||||
if [ -f "src/static/js/prefixfree.js" ]; then
|
||||
VERSION=$(cat src/static/js/prefixfree.js | grep "PrefixFree" | grep -o "[0-9].[0-9].[0-9]");
|
||||
|
||||
if [ $VERSION = $NEEDED_VERSION ]; then
|
||||
DOWNLOAD_PREFIXFREE="false"
|
||||
|
@ -87,7 +93,7 @@ if [ -f "static/js/prefixfree.js" ]; then
|
|||
fi
|
||||
|
||||
if [ $DOWNLOAD_PREFIXFREE = "true" ]; then
|
||||
curl -lo static/js/prefixfree.js -k https://raw.github.com/LeaVerou/prefixfree/master/prefixfree.js || exit 1
|
||||
curl -lo src/static/js/prefixfree.js -k https://raw.github.com/LeaVerou/prefixfree/master/prefixfree.js || exit 1
|
||||
fi
|
||||
|
||||
#Remove all minified data to force node creating it new
|
||||
|
@ -98,12 +104,12 @@ echo "ensure custom css/js files are created..."
|
|||
|
||||
for f in "index" "pad" "timeslider"
|
||||
do
|
||||
if [ ! -f "static/custom/$f.js" ]; then
|
||||
cp -v "static/custom/js.template" "static/custom/$f.js" || exit 1
|
||||
if [ ! -f "src/static/custom/$f.js" ]; then
|
||||
cp -v "src/static/custom/js.template" "src/static/custom/$f.js" || exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "static/custom/$f.css" ]; then
|
||||
cp -v "static/custom/css.template" "static/custom/$f.css" || exit 1
|
||||
if [ ! -f "src/static/custom/$f.css" ]; then
|
||||
cp -v "src/static/custom/css.template" "src/static/custom/$f.css" || exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
|
|
|
@ -25,5 +25,4 @@ bin/installDeps.sh $* || exit 1
|
|||
|
||||
#Move to the node folder and start
|
||||
echo "start..."
|
||||
cd "node"
|
||||
node server.js $*
|
||||
node node_modules/ep_etherpad-lite/node/server.js $*
|
||||
|
|
500
node/server.js
|
@ -1,500 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||
*
|
||||
* 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 ERR = require("async-stacktrace");
|
||||
var log4js = require('log4js');
|
||||
var os = require("os");
|
||||
var socketio = require('socket.io');
|
||||
var fs = require('fs');
|
||||
var settings = require('./utils/Settings');
|
||||
var db = require('./db/DB');
|
||||
var async = require('async');
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
var minify = require('./utils/Minify');
|
||||
var CachingMiddleware = require('./utils/caching_middleware');
|
||||
var Yajsml = require('yajsml');
|
||||
var formidable = require('formidable');
|
||||
var apiHandler;
|
||||
var exportHandler;
|
||||
var importHandler;
|
||||
var exporthtml;
|
||||
var readOnlyManager;
|
||||
var padManager;
|
||||
var securityManager;
|
||||
var socketIORouter;
|
||||
|
||||
//try to get the git version
|
||||
var version = "";
|
||||
try
|
||||
{
|
||||
var rootPath = path.normalize(__dirname + "/../")
|
||||
var ref = fs.readFileSync(rootPath + ".git/HEAD", "utf-8");
|
||||
var refPath = rootPath + ".git/" + ref.substring(5, ref.indexOf("\n"));
|
||||
version = fs.readFileSync(refPath, "utf-8");
|
||||
version = version.substring(0, 7);
|
||||
console.log("Your Etherpad Lite git version is " + version);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.warn("Can't get git version for server header\n" + e.message)
|
||||
}
|
||||
|
||||
console.log("Report bugs at https://github.com/Pita/etherpad-lite/issues")
|
||||
|
||||
var serverName = "Etherpad-Lite " + version + " (http://j.mp/ep-lite)";
|
||||
|
||||
exports.maxAge = settings.maxAge;
|
||||
|
||||
//set loglevel
|
||||
log4js.setGlobalLogLevel(settings.loglevel);
|
||||
|
||||
async.waterfall([
|
||||
//initalize the database
|
||||
function (callback)
|
||||
{
|
||||
db.init(callback);
|
||||
},
|
||||
//initalize the http server
|
||||
function (callback)
|
||||
{
|
||||
//create server
|
||||
var app = express.createServer();
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
res.header("Server", serverName);
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
//redirects browser to the pad's sanitized url if needed. otherwise, renders the html
|
||||
app.param('pad', function (req, res, next, padId) {
|
||||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(padId) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
}
|
||||
else
|
||||
{
|
||||
padManager.sanitizePadId(padId, function(sanitizedPadId) {
|
||||
//the pad id was sanitized, so we redirect to the sanitized version
|
||||
if(sanitizedPadId != padId)
|
||||
{
|
||||
var real_path = req.path.replace(/^\/p\/[^\/]+/, './' + sanitizedPadId);
|
||||
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
|
||||
{
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//load modules that needs a initalized db
|
||||
readOnlyManager = require("./db/ReadOnlyManager");
|
||||
exporthtml = require("./utils/ExportHtml");
|
||||
exportHandler = require('./handler/ExportHandler');
|
||||
importHandler = require('./handler/ImportHandler');
|
||||
apiHandler = require('./handler/APIHandler');
|
||||
padManager = require('./db/PadManager');
|
||||
securityManager = require('./db/SecurityManager');
|
||||
socketIORouter = require("./handler/SocketIORouter");
|
||||
|
||||
//install logging
|
||||
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"))
|
||||
app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.INFO, format: ':status, :method :url'}));
|
||||
app.use(express.cookieParser());
|
||||
});
|
||||
|
||||
app.error(function(err, req, res, next){
|
||||
res.send(500);
|
||||
console.error(err.stack ? err.stack : err.toString());
|
||||
gracefulShutdown();
|
||||
});
|
||||
|
||||
// Cache both minified and static.
|
||||
var assetCache = new CachingMiddleware;
|
||||
app.all('/(minified|static)/*', assetCache.handle);
|
||||
|
||||
// Minify will serve static files compressed (minify enabled). It also has
|
||||
// file-specific hacks for ace/require-kernel/etc.
|
||||
app.all('/static/:filename(*)', minify.minify);
|
||||
|
||||
// Setup middleware that will package JavaScript files served by minify for
|
||||
// CommonJS loader on the client-side.
|
||||
var jsServer = new (Yajsml.Server)({
|
||||
rootPath: 'minified/'
|
||||
, rootURI: 'http://localhost:' + settings.port + '/static/js/'
|
||||
});
|
||||
var StaticAssociator = Yajsml.associators.StaticAssociator;
|
||||
var associations =
|
||||
Yajsml.associators.associationsForSimpleMapping(minify.tar);
|
||||
var associator = new StaticAssociator(associations);
|
||||
jsServer.setAssociator(associator);
|
||||
app.use(jsServer);
|
||||
|
||||
//checks for padAccess
|
||||
function hasPadAccess(req, res, callback)
|
||||
{
|
||||
securityManager.checkAccess(req.params.pad, req.cookies.sessionid, req.cookies.token, req.cookies.password, function(err, accessObj)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//there is access, continue
|
||||
if(accessObj.accessStatus == "grant")
|
||||
{
|
||||
callback();
|
||||
}
|
||||
//no access
|
||||
else
|
||||
{
|
||||
res.send("403 - Can't touch this", 403);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
var html;
|
||||
var padId;
|
||||
var pad;
|
||||
|
||||
async.series([
|
||||
//translate the read only pad to a padId
|
||||
function(callback)
|
||||
{
|
||||
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();
|
||||
});
|
||||
},
|
||||
//render the html document
|
||||
function(callback)
|
||||
{
|
||||
//return if the there is no padId
|
||||
if(padId == null)
|
||||
{
|
||||
callback("notfound");
|
||||
return;
|
||||
}
|
||||
|
||||
hasPadAccess(req, res, function()
|
||||
{
|
||||
//render the html document
|
||||
exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
html = _html;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
//throw any unexpected error
|
||||
if(err && err != "notfound")
|
||||
ERR(err);
|
||||
|
||||
if(err == "notfound")
|
||||
res.send('404 - Not Found', 404);
|
||||
else
|
||||
res.send(html);
|
||||
});
|
||||
});
|
||||
|
||||
//serve pad.html under /p
|
||||
app.get('/p/:pad', function(req, res, next)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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/:rev?/export/:type', function(req, res, next)
|
||||
{
|
||||
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)
|
||||
{
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
//if abiword is disabled, and this is a format we only support with abiword, output a message
|
||||
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;
|
||||
}
|
||||
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
|
||||
hasPadAccess(req, res, function()
|
||||
{
|
||||
exportHandler.doExport(req, res, req.params.pad, req.params.type);
|
||||
});
|
||||
});
|
||||
|
||||
//handle import requests
|
||||
app.post('/p/:pad/import', function(req, res, next)
|
||||
{
|
||||
//if abiword is disabled, skip handling this request
|
||||
if(settings.abiword == null)
|
||||
{
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
hasPadAccess(req, res, function()
|
||||
{
|
||||
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)
|
||||
{
|
||||
res.header("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
apiLogger.info("REQUEST, " + req.params.func + ", " + JSON.stringify(fields));
|
||||
|
||||
//wrap the send function so we can log the response
|
||||
res._send = res.send;
|
||||
res.send = function(response)
|
||||
{
|
||||
response = JSON.stringify(response);
|
||||
apiLogger.info("RESPONSE, " + req.params.func + ", " + response);
|
||||
|
||||
//is this a jsonp call, if yes, add the function call
|
||||
if(req.query.jsonp)
|
||||
response = req.query.jsonp + "(" + response + ")";
|
||||
|
||||
res._send(response);
|
||||
}
|
||||
|
||||
//call the api handler
|
||||
apiHandler.handle(req.params.func, fields, req, res);
|
||||
}
|
||||
|
||||
//This is a api GET call, collect all post informations and pass it to the apiHandler
|
||||
app.get('/api/1/:func', function(req, res)
|
||||
{
|
||||
apiCaller(req, res, req.query)
|
||||
});
|
||||
|
||||
//This is a api POST call, collect all post informations and pass it to the apiHandler
|
||||
app.post('/api/1/:func', function(req, res)
|
||||
{
|
||||
new formidable.IncomingForm().parse(req, function(err, fields, files)
|
||||
{
|
||||
apiCaller(req, res, fields)
|
||||
});
|
||||
});
|
||||
|
||||
//The Etherpad client side sends information about how a disconnect happen
|
||||
app.post('/ep/pad/connection-diagnostic-info', function(req, res)
|
||||
{
|
||||
new formidable.IncomingForm().parse(req, function(err, fields, files)
|
||||
{
|
||||
console.log("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
|
||||
res.end("OK");
|
||||
});
|
||||
});
|
||||
|
||||
//The Etherpad client side sends information about client side javscript errors
|
||||
app.post('/jserror', function(req, res)
|
||||
{
|
||||
new formidable.IncomingForm().parse(req, function(err, fields, files)
|
||||
{
|
||||
console.error("CLIENT SIDE JAVASCRIPT ERROR: " + fields.errorInfo);
|
||||
res.end("OK");
|
||||
});
|
||||
});
|
||||
|
||||
//serve index.html under /
|
||||
app.get('/', function(req, res)
|
||||
{
|
||||
var filePath = path.normalize(__dirname + "/../static/index.html");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
|
||||
//serve robots.txt
|
||||
app.get('/robots.txt', function(req, res)
|
||||
{
|
||||
var filePath = path.normalize(__dirname + "/../static/robots.txt");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
|
||||
//serve favicon.ico
|
||||
app.get('/favicon.ico', function(req, res)
|
||||
{
|
||||
var filePath = path.normalize(__dirname + "/../static/custom/favicon.ico");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge }, function(err)
|
||||
{
|
||||
//there is no custom favicon, send the default favicon
|
||||
if(err)
|
||||
{
|
||||
filePath = path.normalize(__dirname + "/../static/favicon.ico");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//let the server listen
|
||||
app.listen(settings.port, settings.ip);
|
||||
console.log("Server is listening at " + settings.ip + ":" + settings.port);
|
||||
|
||||
var onShutdown = false;
|
||||
var gracefulShutdown = function(err)
|
||||
{
|
||||
if(err && err.stack)
|
||||
{
|
||||
console.error(err.stack);
|
||||
}
|
||||
else if(err)
|
||||
{
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
//ensure there is only one graceful shutdown running
|
||||
if(onShutdown) return;
|
||||
onShutdown = true;
|
||||
|
||||
console.log("graceful shutdown...");
|
||||
|
||||
//stop the http server
|
||||
app.close();
|
||||
|
||||
//do the db shutdown
|
||||
db.db.doShutdown(function()
|
||||
{
|
||||
console.log("db sucessfully closed.");
|
||||
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
setTimeout(function(){
|
||||
process.exit(1);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
//connect graceful shutdown with sigint and uncaughtexception
|
||||
if(os.type().indexOf("Windows") == -1)
|
||||
{
|
||||
//sigint is so far not working on windows
|
||||
//https://github.com/joyent/node/issues/1553
|
||||
process.on('SIGINT', gracefulShutdown);
|
||||
}
|
||||
|
||||
process.on('uncaughtException', gracefulShutdown);
|
||||
|
||||
//init socket.io and redirect all requests to the MessageHandler
|
||||
var io = socketio.listen(app);
|
||||
|
||||
//this is only a workaround to ensure it works with all browers behind a proxy
|
||||
//we should remove this when the new socket.io version is more stable
|
||||
io.set('transports', ['xhr-polling']);
|
||||
|
||||
var socketIOLogger = log4js.getLogger("socket.io");
|
||||
io.set('logger', {
|
||||
debug: function (str)
|
||||
{
|
||||
socketIOLogger.debug.apply(socketIOLogger, arguments);
|
||||
},
|
||||
info: function (str)
|
||||
{
|
||||
socketIOLogger.info.apply(socketIOLogger, arguments);
|
||||
},
|
||||
warn: function (str)
|
||||
{
|
||||
socketIOLogger.warn.apply(socketIOLogger, arguments);
|
||||
},
|
||||
error: function (str)
|
||||
{
|
||||
socketIOLogger.error.apply(socketIOLogger, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
//minify socket.io javascript
|
||||
if(settings.minify)
|
||||
io.enable('browser client minification');
|
||||
|
||||
var padMessageHandler = require("./handler/PadMessageHandler");
|
||||
var timesliderMessageHandler = require("./handler/TimesliderMessageHandler");
|
||||
|
||||
//Initalize the Socket.IO Router
|
||||
socketIORouter.setSocketIO(io);
|
||||
socketIORouter.addComponent("pad", padMessageHandler);
|
||||
socketIORouter.addComponent("timeslider", timesliderMessageHandler);
|
||||
|
||||
callback(null);
|
||||
}
|
||||
]);
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var RequireKernel = require('require-kernel/');
|
||||
var path = require('path');
|
||||
|
||||
var CLIENT_JS_SRC = path.normalize(__dirname + '/../../static/js/');
|
||||
var client_require = RequireKernel.requireForPaths(
|
||||
'file://' + (CLIENT_JS_SRC.charAt(0) == '/' ? '' : '/') + encodeURI(CLIENT_JS_SRC));
|
||||
|
||||
exports.require = client_require;
|
|
@ -13,7 +13,7 @@
|
|||
"dbType" : "dirty",
|
||||
//the database specific settings
|
||||
"dbSettings" : {
|
||||
"filename" : "../var/dirty.db"
|
||||
"filename" : "var/dirty.db"
|
||||
},
|
||||
|
||||
/* An Example of MySQL Configuration
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"dbType" : "dirty",
|
||||
//the database specific settings
|
||||
"dbSettings" : {
|
||||
"filename" : "../var/dirty.db"
|
||||
"filename" : "var/dirty.db"
|
||||
},
|
||||
|
||||
/* An Example of MySQL Configuration
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"parts": [
|
||||
{ "name": "static", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/static:expressCreateServer" } },
|
||||
{ "name": "specialpages", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/specialpages:expressCreateServer" } },
|
||||
{ "name": "padurlsanitize", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/padurlsanitize:expressCreateServer" } },
|
||||
{ "name": "padreadonly", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/padreadonly:expressCreateServer" } },
|
||||
{ "name": "webaccess", "hooks": { "expressConfigure": "ep_etherpad-lite/node/hooks/express/webaccess:expressConfigure" } },
|
||||
{ "name": "apicalls", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/apicalls:expressCreateServer" } },
|
||||
{ "name": "importexport", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/importexport:expressCreateServer" } },
|
||||
{ "name": "errorhandling", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/errorhandling:expressCreateServer" } },
|
||||
{ "name": "socketio", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/socketio:expressCreateServer" } }
|
||||
|
||||
]
|
||||
}
|
|
@ -18,11 +18,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var randomString = CommonCode.require('/pad_utils').randomString;
|
||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||
|
||||
/**
|
||||
* Checks if the author exists
|
|
@ -18,10 +18,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var customError = require("../utils/customError");
|
||||
var randomString = CommonCode.require('/pad_utils').randomString;
|
||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var padManager = require("./PadManager");
|
|
@ -2,11 +2,11 @@
|
|||
* The pad object, defined with joose
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||
var randomString = CommonCode.require('/pad_utils').randomString;
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var AttributePoolFactory = require("ep_etherpad-lite/static/js/AttributePoolFactory");
|
||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var settings = require('../utils/Settings');
|
|
@ -18,11 +18,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var randomString = CommonCode.require('/pad_utils').randomString;
|
||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||
|
||||
/**
|
||||
* returns a read only id for a pad
|
|
@ -18,7 +18,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
|
@ -26,7 +26,7 @@ var authorManager = require("./AuthorManager");
|
|||
var padManager = require("./PadManager");
|
||||
var sessionManager = require("./SessionManager");
|
||||
var settings = require("../utils/Settings")
|
||||
var randomString = CommonCode.require('/pad_utils').randomString;
|
||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||
|
||||
/**
|
||||
* This function controlls the access to a pad, it checks if the user can access a pad.
|
|
@ -18,10 +18,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var customError = require("../utils/customError");
|
||||
var randomString = CommonCode.require('/pad_utils').randomString;
|
||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var groupMangager = require("./GroupManager");
|
|
@ -20,9 +20,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('./utils/common_code');
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var AttributePoolFactory = require("ep_etherpad-lite/static/js/AttributePoolFactory");
|
||||
|
||||
function random() {
|
||||
this.nextInt = function (maxValue) {
|
|
@ -18,12 +18,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var fs = require("fs");
|
||||
var api = require("../db/API");
|
||||
var padManager = require("../db/PadManager");
|
||||
var randomString = CommonCode.require('/pad_utils').randomString;
|
||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||
|
||||
//ensure we have an apikey
|
||||
var apikey = null;
|
|
@ -18,16 +18,17 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var async = require("async");
|
||||
var padManager = require("../db/PadManager");
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var AttributePoolFactory = require("ep_etherpad-lite/static/js/AttributePoolFactory");
|
||||
var authorManager = require("../db/AuthorManager");
|
||||
var readOnlyManager = require("../db/ReadOnlyManager");
|
||||
var settings = require('../utils/Settings');
|
||||
var securityManager = require("../db/SecurityManager");
|
||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins.js");
|
||||
var log4js = require('log4js');
|
||||
var messageLogger = log4js.getLogger("message");
|
||||
|
||||
|
@ -800,7 +801,10 @@ function handleClientReady(client, message)
|
|||
"hideSidebar": false
|
||||
},
|
||||
"abiwordAvailable": settings.abiwordAvailable(),
|
||||
"hooks": {}
|
||||
"plugins": {
|
||||
"plugins": plugins.plugins,
|
||||
"parts": plugins.parts,
|
||||
}
|
||||
}
|
||||
|
||||
//Add a username to the clientVars if one avaiable
|
|
@ -18,12 +18,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
|
||||
var ERR = require("async-stacktrace");
|
||||
var async = require("async");
|
||||
var padManager = require("../db/PadManager");
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var AttributePoolFactory = require("ep_etherpad-lite/static/js/AttributePoolFactory");
|
||||
var settings = require('../utils/Settings');
|
||||
var authorManager = require("../db/AuthorManager");
|
||||
var log4js = require('log4js');
|
|
@ -0,0 +1,58 @@
|
|||
var log4js = require('log4js');
|
||||
var apiLogger = log4js.getLogger("API");
|
||||
var formidable = require('formidable');
|
||||
var apiHandler = require('../../handler/APIHandler');
|
||||
|
||||
//This is for making an api call, collecting all post information and passing it to the apiHandler
|
||||
exports.apiCaller = function(req, res, fields) {
|
||||
res.header("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
apiLogger.info("REQUEST, " + req.params.func + ", " + JSON.stringify(fields));
|
||||
|
||||
//wrap the send function so we can log the response
|
||||
res._send = res.send;
|
||||
res.send = function (response) {
|
||||
response = JSON.stringify(response);
|
||||
apiLogger.info("RESPONSE, " + req.params.func + ", " + response);
|
||||
|
||||
//is this a jsonp call, if yes, add the function call
|
||||
if(req.query.jsonp)
|
||||
response = req.query.jsonp + "(" + response + ")";
|
||||
|
||||
res._send(response);
|
||||
}
|
||||
|
||||
//call the api handler
|
||||
apiHandler.handle(req.params.func, fields, req, res);
|
||||
}
|
||||
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
//This is a api GET call, collect all post informations and pass it to the apiHandler
|
||||
args.app.get('/api/1/:func', function (req, res) {
|
||||
apiCaller(req, res, req.query)
|
||||
});
|
||||
|
||||
//This is a api POST call, collect all post informations and pass it to the apiHandler
|
||||
args.app.post('/api/1/:func', function(req, res) {
|
||||
new formidable.IncomingForm().parse(req, function (err, fields, files) {
|
||||
apiCaller(req, res, fields)
|
||||
});
|
||||
});
|
||||
|
||||
//The Etherpad client side sends information about how a disconnect happen
|
||||
args.app.post('/ep/pad/connection-diagnostic-info', function(req, res) {
|
||||
new formidable.IncomingForm().parse(req, function(err, fields, files) {
|
||||
console.log("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
|
||||
res.end("OK");
|
||||
});
|
||||
});
|
||||
|
||||
//The Etherpad client side sends information about client side javscript errors
|
||||
args.app.post('/jserror', function(req, res) {
|
||||
new formidable.IncomingForm().parse(req, function(err, fields, files) {
|
||||
console.error("CLIENT SIDE JAVASCRIPT ERROR: " + fields.errorInfo);
|
||||
res.end("OK");
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
var os = require("os");
|
||||
var db = require('../../db/DB');
|
||||
|
||||
|
||||
exports.onShutdown = false;
|
||||
exports.gracefulShutdown = function(err) {
|
||||
if(err && err.stack) {
|
||||
console.error(err.stack);
|
||||
} else if(err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
//ensure there is only one graceful shutdown running
|
||||
if(exports.onShutdown) return;
|
||||
exports.onShutdown = true;
|
||||
|
||||
console.log("graceful shutdown...");
|
||||
|
||||
//stop the http server
|
||||
exports.app.close();
|
||||
|
||||
//do the db shutdown
|
||||
db.db.doShutdown(function() {
|
||||
console.log("db sucessfully closed.");
|
||||
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
setTimeout(function(){
|
||||
process.exit(1);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
exports.app = args.app;
|
||||
|
||||
args.app.error(function(err, req, res, next){
|
||||
res.send(500);
|
||||
console.error(err.stack ? err.stack : err.toString());
|
||||
exports.gracefulShutdown();
|
||||
});
|
||||
|
||||
//connect graceful shutdown with sigint and uncaughtexception
|
||||
if(os.type().indexOf("Windows") == -1) {
|
||||
//sigint is so far not working on windows
|
||||
//https://github.com/joyent/node/issues/1553
|
||||
process.on('SIGINT', exports.gracefulShutdown);
|
||||
}
|
||||
|
||||
process.on('uncaughtException', exports.gracefulShutdown);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
var hasPadAccess = require("../../padaccess");
|
||||
var settings = require('../../utils/Settings');
|
||||
var exportHandler = require('../../handler/ExportHandler');
|
||||
var importHandler = require('../../handler/ImportHandler');
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
args.app.get('/p/:pad/:rev?/export/:type', function(req, res, next) {
|
||||
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) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
//if abiword is disabled, and this is a format we only support with abiword, output a message
|
||||
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;
|
||||
}
|
||||
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
|
||||
hasPadAccess(req, res, function() {
|
||||
exportHandler.doExport(req, res, req.params.pad, req.params.type);
|
||||
});
|
||||
});
|
||||
|
||||
//handle import requests
|
||||
args.app.post('/p/:pad/import', function(req, res, next) {
|
||||
//if abiword is disabled, skip handling this request
|
||||
if(settings.abiword == null) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
hasPadAccess(req, res, function() {
|
||||
importHandler.doImport(req, res, req.params.pad);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
var async = require('async');
|
||||
var ERR = require("async-stacktrace");
|
||||
var readOnlyManager = require("../../db/ReadOnlyManager");
|
||||
var hasPadAccess = require("../../padaccess");
|
||||
var exporthtml = require("../../utils/ExportHtml");
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
//serve read only pad
|
||||
args.app.get('/ro/:id', function(req, res)
|
||||
{
|
||||
var html;
|
||||
var padId;
|
||||
var pad;
|
||||
|
||||
async.series([
|
||||
//translate the read only pad to a padId
|
||||
function(callback)
|
||||
{
|
||||
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();
|
||||
});
|
||||
},
|
||||
//render the html document
|
||||
function(callback)
|
||||
{
|
||||
//return if the there is no padId
|
||||
if(padId == null)
|
||||
{
|
||||
callback("notfound");
|
||||
return;
|
||||
}
|
||||
|
||||
hasPadAccess(req, res, function()
|
||||
{
|
||||
//render the html document
|
||||
exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
html = _html;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
//throw any unexpected error
|
||||
if(err && err != "notfound")
|
||||
ERR(err);
|
||||
|
||||
if(err == "notfound")
|
||||
res.send('404 - Not Found', 404);
|
||||
else
|
||||
res.send(html);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
var padManager = require('../../db/PadManager');
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
//redirects browser to the pad's sanitized url if needed. otherwise, renders the html
|
||||
args.app.param('pad', function (req, res, next, padId) {
|
||||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(padId) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
}
|
||||
else
|
||||
{
|
||||
padManager.sanitizePadId(padId, function(sanitizedPadId) {
|
||||
//the pad id was sanitized, so we redirect to the sanitized version
|
||||
if(sanitizedPadId != padId)
|
||||
{
|
||||
var real_path = req.path.replace(/^\/p\/[^\/]+/, '/p/' + sanitizedPadId);
|
||||
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
|
||||
{
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
var log4js = require('log4js');
|
||||
var socketio = require('socket.io');
|
||||
var settings = require('../../utils/Settings');
|
||||
var socketIORouter = require("../../handler/SocketIORouter");
|
||||
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
|
||||
|
||||
var padMessageHandler = require("../../handler/PadMessageHandler");
|
||||
var timesliderMessageHandler = require("../../handler/TimesliderMessageHandler");
|
||||
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
//init socket.io and redirect all requests to the MessageHandler
|
||||
var io = socketio.listen(args.app);
|
||||
|
||||
//this is only a workaround to ensure it works with all browers behind a proxy
|
||||
//we should remove this when the new socket.io version is more stable
|
||||
io.set('transports', ['xhr-polling']);
|
||||
|
||||
var socketIOLogger = log4js.getLogger("socket.io");
|
||||
io.set('logger', {
|
||||
debug: function (str)
|
||||
{
|
||||
socketIOLogger.debug.apply(socketIOLogger, arguments);
|
||||
},
|
||||
info: function (str)
|
||||
{
|
||||
socketIOLogger.info.apply(socketIOLogger, arguments);
|
||||
},
|
||||
warn: function (str)
|
||||
{
|
||||
socketIOLogger.warn.apply(socketIOLogger, arguments);
|
||||
},
|
||||
error: function (str)
|
||||
{
|
||||
socketIOLogger.error.apply(socketIOLogger, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
//minify socket.io javascript
|
||||
if(settings.minify)
|
||||
io.enable('browser client minification');
|
||||
|
||||
//Initalize the Socket.IO Router
|
||||
socketIORouter.setSocketIO(io);
|
||||
socketIORouter.addComponent("pad", padMessageHandler);
|
||||
socketIORouter.addComponent("timeslider", timesliderMessageHandler);
|
||||
|
||||
hooks.callAll("socketio", {"app": args.app, "io": io});
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
var path = require('path');
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
|
||||
//serve index.html under /
|
||||
args.app.get('/', function(req, res)
|
||||
{
|
||||
var filePath = path.normalize(__dirname + "/../../../static/index.html");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
|
||||
//serve robots.txt
|
||||
args.app.get('/robots.txt', function(req, res)
|
||||
{
|
||||
var filePath = path.normalize(__dirname + "/../../../static/robots.txt");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
|
||||
//serve favicon.ico
|
||||
args.app.get('/favicon.ico', function(req, res)
|
||||
{
|
||||
var filePath = path.normalize(__dirname + "/../../../static/custom/favicon.ico");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge }, function(err)
|
||||
{
|
||||
//there is no custom favicon, send the default favicon
|
||||
if(err)
|
||||
{
|
||||
filePath = path.normalize(__dirname + "/../../../static/favicon.ico");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//serve pad.html under /p
|
||||
args.app.get('/p/:pad', function(req, res, next)
|
||||
{
|
||||
var filePath = path.normalize(__dirname + "/../../../static/pad.html");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
|
||||
//serve timeslider.html under /p/$padname/timeslider
|
||||
args.app.get('/p/:pad/timeslider', function(req, res, next)
|
||||
{
|
||||
var filePath = path.normalize(__dirname + "/../../../static/timeslider.html");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
var path = require('path');
|
||||
var minify = require('../../utils/Minify');
|
||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
|
||||
var CachingMiddleware = require('../../utils/caching_middleware');
|
||||
var settings = require("../../utils/Settings");
|
||||
var Yajsml = require('yajsml');
|
||||
var fs = require("fs");
|
||||
var ERR = require("async-stacktrace");
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
// Cache both minified and static.
|
||||
var assetCache = new CachingMiddleware;
|
||||
args.app.all('/(javascripts|static)/*', assetCache.handle);
|
||||
|
||||
// Minify will serve static files compressed (minify enabled). It also has
|
||||
// file-specific hacks for ace/require-kernel/etc.
|
||||
args.app.all('/static/:filename(*)', minify.minify);
|
||||
|
||||
// Setup middleware that will package JavaScript files served by minify for
|
||||
// CommonJS loader on the client-side.
|
||||
var jsServer = new (Yajsml.Server)({
|
||||
rootPath: 'javascripts/src/'
|
||||
, rootURI: 'http://localhost:' + settings.port + '/static/js/'
|
||||
, libraryPath: 'javascripts/lib/'
|
||||
, libraryURI: 'http://localhost:' + settings.port + '/static/plugins/'
|
||||
});
|
||||
|
||||
var StaticAssociator = Yajsml.associators.StaticAssociator;
|
||||
var associations =
|
||||
Yajsml.associators.associationsForSimpleMapping(minify.tar);
|
||||
var associator = new StaticAssociator(associations);
|
||||
jsServer.setAssociator(associator);
|
||||
args.app.use(jsServer);
|
||||
|
||||
// serve plugin definitions
|
||||
// not very static, but served here so that client can do require("pluginfw/static/js/plugin-definitions.js");
|
||||
args.app.get('/pluginfw/plugin-definitions.json', function (req, res, next) {
|
||||
res.header("Content-Type","application/json; charset: utf-8");
|
||||
res.write(JSON.stringify({"plugins": plugins.plugins, "parts": plugins.parts}));
|
||||
res.end();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
var express = require('express');
|
||||
var log4js = require('log4js');
|
||||
var httpLogger = log4js.getLogger("http");
|
||||
var settings = require('../../utils/Settings');
|
||||
|
||||
|
||||
//checks for basic http auth
|
||||
exports.basicAuth = function (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);
|
||||
}
|
||||
}
|
||||
|
||||
exports.expressConfigure = function (hook_name, args, cb) {
|
||||
// Activate http basic auth if it has been defined in settings.json
|
||||
if(settings.httpAuth != null) args.app.use(exports.basicAuth);
|
||||
|
||||
// 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"))
|
||||
args.app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.INFO, format: ':status, :method :url'}));
|
||||
args.app.use(express.cookieParser());
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
var ERR = require("async-stacktrace");
|
||||
var securityManager = require('./db/SecurityManager');
|
||||
|
||||
//checks for padAccess
|
||||
module.exports = function (req, res, callback) {
|
||||
|
||||
// FIXME: Why is this ever undefined??
|
||||
if (req.cookies === undefined) req.cookies = {};
|
||||
|
||||
securityManager.checkAccess(req.params.pad, req.cookies.sessionid, req.cookies.token, req.cookies.password, function(err, accessObj) {
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//there is access, continue
|
||||
if(accessObj.accessStatus == "grant") {
|
||||
callback();
|
||||
//no access
|
||||
} else {
|
||||
res.send("403 - Can't touch this", 403);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||
*
|
||||
* 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 log4js = require('log4js');
|
||||
var fs = require('fs');
|
||||
var settings = require('./utils/Settings');
|
||||
var db = require('./db/DB');
|
||||
var async = require('async');
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
|
||||
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
|
||||
var npm = require("npm/lib/npm.js");
|
||||
|
||||
//try to get the git version
|
||||
var version = "";
|
||||
try
|
||||
{
|
||||
var rootPath = path.resolve(npm.dir, '..');
|
||||
var ref = fs.readFileSync(rootPath + "/.git/HEAD", "utf-8");
|
||||
var refPath = rootPath + "/.git/" + ref.substring(5, ref.indexOf("\n"));
|
||||
version = fs.readFileSync(refPath, "utf-8");
|
||||
version = version.substring(0, 7);
|
||||
console.log("Your Etherpad Lite git version is " + version);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.warn("Can't get git version for server header\n" + e.message)
|
||||
}
|
||||
|
||||
console.log("Report bugs at https://github.com/Pita/etherpad-lite/issues")
|
||||
|
||||
var serverName = "Etherpad-Lite " + version + " (http://j.mp/ep-lite)";
|
||||
|
||||
//cache 6 hours
|
||||
exports.maxAge = 1000*60*60*6;
|
||||
|
||||
//set loglevel
|
||||
log4js.setGlobalLogLevel(settings.loglevel);
|
||||
|
||||
async.waterfall([
|
||||
//initalize the database
|
||||
function (callback)
|
||||
{
|
||||
db.init(callback);
|
||||
},
|
||||
|
||||
plugins.update,
|
||||
|
||||
function (callback) {
|
||||
console.log("Installed plugins: " + plugins.formatPlugins());
|
||||
console.log("Installed parts:\n" + plugins.formatParts());
|
||||
console.log("Installed hooks:\n" + plugins.formatHooks());
|
||||
callback();
|
||||
},
|
||||
|
||||
//initalize the http server
|
||||
function (callback)
|
||||
{
|
||||
//create server
|
||||
var app = express.createServer();
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
res.header("Server", serverName);
|
||||
next();
|
||||
});
|
||||
|
||||
app.configure(function() { hooks.callAll("expressConfigure", {"app": app}); });
|
||||
|
||||
hooks.callAll("expressCreateServer", {"app": app});
|
||||
|
||||
//let the server listen
|
||||
app.listen(settings.port, settings.ip);
|
||||
console.log("Server is listening at " + settings.ip + ":" + settings.port);
|
||||
|
||||
callback(null);
|
||||
}
|
||||
]);
|
|
@ -15,8 +15,8 @@
|
|||
*/
|
||||
|
||||
var async = require("async");
|
||||
var CommonCode = require('./common_code');
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var padManager = require("../db/PadManager");
|
||||
|
||||
function getPadDokuWiki(pad, revNum, callback)
|
|
@ -14,12 +14,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var CommonCode = require('./common_code');
|
||||
|
||||
var async = require("async");
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var padManager = require("../db/PadManager");
|
||||
var ERR = require("async-stacktrace");
|
||||
var Security = CommonCode.require('/security');
|
||||
var Security = require('ep_etherpad-lite/static/js/security');
|
||||
|
||||
function getPadPlainText(pad, revNum)
|
||||
{
|
|
@ -17,10 +17,10 @@
|
|||
var jsdom = require('jsdom-nocontextifiy').jsdom;
|
||||
var log4js = require('log4js');
|
||||
|
||||
var CommonCode = require('../utils/common_code');
|
||||
var Changeset = CommonCode.require("/Changeset");
|
||||
var contentcollector = CommonCode.require("/contentcollector");
|
||||
var map = CommonCode.require("/ace2_common").map;
|
||||
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var contentcollector = require("ep_etherpad-lite/static/js/contentcollector");
|
||||
var map = require("ep_etherpad-lite/static/js/ace2_common").map;
|
||||
|
||||
function setPadHTML(pad, html, callback)
|
||||
{
|
|
@ -27,6 +27,7 @@ var cleanCSS = require('clean-css');
|
|||
var jsp = require("uglify-js").parser;
|
||||
var pro = require("uglify-js").uglify;
|
||||
var path = require('path');
|
||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
|
||||
var RequireKernel = require('require-kernel');
|
||||
var server = require('../server');
|
||||
|
||||
|
@ -35,11 +36,14 @@ var TAR_PATH = path.join(__dirname, 'tar.json');
|
|||
var tar = JSON.parse(fs.readFileSync(TAR_PATH, 'utf8'));
|
||||
|
||||
// Rewrite tar to include modules with no extensions and proper rooted paths.
|
||||
var LIBRARY_PREFIX = 'ep_etherpad-lite/static/js';
|
||||
exports.tar = {};
|
||||
for (var key in tar) {
|
||||
exports.tar['/' + key] =
|
||||
tar[key].map(function (p) {return '/' + p}).concat(
|
||||
tar[key].map(function (p) {return '/' + p.replace(/\.js$/, '')})
|
||||
exports.tar[LIBRARY_PREFIX + '/' + key] =
|
||||
tar[key].map(function (p) {return LIBRARY_PREFIX + '/' + p}).concat(
|
||||
tar[key].map(function (p) {
|
||||
return LIBRARY_PREFIX + '/' + p.replace(/\.js$/, '')
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -63,6 +67,22 @@ exports.minify = function(req, res, next)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Handle static files for plugins:
|
||||
paths like "plugins/ep_myplugin/static/js/test.js"
|
||||
are rewritten into ROOT_PATH_OF_MYPLUGIN/static/js/test.js,
|
||||
commonly ETHERPAD_ROOT/node_modules/ep_myplugin/static/js/test.js
|
||||
*/
|
||||
var match = filename.match(/^plugins\/([^\/]+)\/static\/(.*)/);
|
||||
if (match) {
|
||||
var pluginName = match[1];
|
||||
var resourcePath = match[2];
|
||||
var plugin = plugins.plugins[pluginName];
|
||||
if (plugin) {
|
||||
var pluginPath = plugin.package.realPath;
|
||||
filename = path.relative(ROOT_DIR, pluginPath + '/static/' + resourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
// What content type should this be?
|
||||
// TODO: This should use a MIME module.
|
||||
var contentType;
|
|
@ -0,0 +1,513 @@
|
|||
/**
|
||||
* This Module manages all /minified/* requests. It controls the
|
||||
* minification && compression of Javascript and CSS.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||
*
|
||||
* 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 ERR = require("async-stacktrace");
|
||||
var settings = require('./Settings');
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
var cleanCSS = require('clean-css');
|
||||
var jsp = require("uglify-js").parser;
|
||||
var pro = require("uglify-js").uglify;
|
||||
var path = require('path');
|
||||
var RequireKernel = require('require-kernel');
|
||||
var server = require('../server');
|
||||
|
||||
<<<<<<< HEAD
|
||||
var ROOT_DIR = path.normalize(__dirname + "/../" );
|
||||
var JS_DIR = ROOT_DIR + '../static/js/';
|
||||
var CSS_DIR = ROOT_DIR + '../static/css/';
|
||||
var CACHE_DIR = path.join(settings.root, 'var');
|
||||
=======
|
||||
var ROOT_DIR = path.normalize(__dirname + "/../../static/");
|
||||
>>>>>>> pita
|
||||
var TAR_PATH = path.join(__dirname, 'tar.json');
|
||||
var tar = JSON.parse(fs.readFileSync(TAR_PATH, 'utf8'));
|
||||
|
||||
// Rewrite tar to include modules with no extensions and proper rooted paths.
|
||||
exports.tar = {};
|
||||
for (var key in tar) {
|
||||
exports.tar['/' + key] =
|
||||
tar[key].map(function (p) {return '/' + p}).concat(
|
||||
tar[key].map(function (p) {return '/' + p.replace(/\.js$/, '')})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the minifed javascript for the given minified name
|
||||
* @param req the Express request
|
||||
* @param res the Express response
|
||||
*/
|
||||
exports.minify = function(req, res, next)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
var jsFilename = req.params[0];
|
||||
|
||||
//choose the js files we need
|
||||
var jsFiles = undefined;
|
||||
if (Object.prototype.hasOwnProperty.call(tar, jsFilename)) {
|
||||
jsFiles = tar[jsFilename];
|
||||
} else {
|
||||
/* Not in tar list, but try anyways, if it fails, pass to `next`.
|
||||
Actually try, not check in filesystem here because
|
||||
we don't want to duplicate the require.resolve() handling
|
||||
*/
|
||||
jsFiles = [jsFilename];
|
||||
}
|
||||
_handle(req, res, jsFilename, jsFiles, function (err) {
|
||||
console.log("Unable to load minified file " + jsFilename + ": " + err.toString());
|
||||
/* Throw away error and generate a 404, not 500 */
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function _handle(req, res, jsFilename, jsFiles, next) {
|
||||
res.header("Content-Type","text/javascript");
|
||||
|
||||
var cacheName = CACHE_DIR + "/minified_" + jsFilename.replace(/\//g, "_");
|
||||
|
||||
//minifying is enabled
|
||||
if(settings.minify)
|
||||
{
|
||||
var result = undefined;
|
||||
var latestModification = 0;
|
||||
|
||||
async.series([
|
||||
//find out the highest modification date
|
||||
function(callback)
|
||||
{
|
||||
var folders2check = [CSS_DIR, JS_DIR];
|
||||
|
||||
//go trough this two folders
|
||||
async.forEach(folders2check, function(path, callback)
|
||||
{
|
||||
//read the files in the folder
|
||||
fs.readdir(path, function(err, files)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//we wanna check the directory itself for changes too
|
||||
files.push(".");
|
||||
|
||||
//go trough all files in this folder
|
||||
async.forEach(files, function(filename, callback)
|
||||
{
|
||||
//get the stat data of this file
|
||||
fs.stat(path + "/" + filename, function(err, stats)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//get the modification time
|
||||
var modificationTime = stats.mtime.getTime();
|
||||
|
||||
//compare the modification time to the highest found
|
||||
if(modificationTime > latestModification)
|
||||
{
|
||||
latestModification = modificationTime;
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
});
|
||||
}, callback);
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
//check the modification time of the minified js
|
||||
fs.stat(cacheName, function(err, stats)
|
||||
{
|
||||
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)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
//the minified file is still up to date, stop minifying
|
||||
else
|
||||
{
|
||||
callback("stop");
|
||||
}
|
||||
});
|
||||
},
|
||||
//load all js files
|
||||
function (callback)
|
||||
{
|
||||
var values = [];
|
||||
tarCode(
|
||||
jsFiles
|
||||
, function (content) {values.push(content)}
|
||||
, function (err) {
|
||||
if(ERR(err, next)) return;
|
||||
|
||||
result = values.join('');
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//put all together and write it into a file
|
||||
function(callback)
|
||||
{
|
||||
async.parallel([
|
||||
//write the results plain in a file
|
||||
function(callback)
|
||||
{
|
||||
fs.writeFile(cacheName, result, "utf8", callback);
|
||||
},
|
||||
//write the results compressed in a file
|
||||
function(callback)
|
||||
{
|
||||
zlib.gzip(result, function(err, compressedResult){
|
||||
//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(cacheName + ".gz", compressedResult, callback);
|
||||
});
|
||||
}
|
||||
],callback);
|
||||
}
|
||||
], function(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;
|
||||
|
||||
var pathStr;
|
||||
if(gzipSupport && os.type().indexOf("Windows") == -1)
|
||||
{
|
||||
pathStr = path.normalize(cacheName + ".gz");
|
||||
res.header('Content-Encoding', 'gzip');
|
||||
}
|
||||
else
|
||||
{
|
||||
pathStr = path.normalize(cacheName);
|
||||
}
|
||||
|
||||
res.sendfile(pathStr, { maxAge: server.maxAge });
|
||||
})
|
||||
}
|
||||
//minifying is disabled, so put the files together in one file
|
||||
else
|
||||
{
|
||||
tarCode(
|
||||
jsFiles
|
||||
, function (content) {res.write(content)}
|
||||
, function (err) {
|
||||
if(ERR(err, next)) return;
|
||||
=======
|
||||
var filename = req.params['filename'];
|
||||
|
||||
// No relative paths, especially if they may go up the file hierarchy.
|
||||
filename = path.normalize(path.join(ROOT_DIR, filename));
|
||||
if (filename.indexOf(ROOT_DIR) == 0) {
|
||||
filename = filename.slice(ROOT_DIR.length);
|
||||
filename = filename.replace(/\\/g, '/'); // Windows (safe generally?)
|
||||
} else {
|
||||
res.writeHead(404, {});
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// What content type should this be?
|
||||
// TODO: This should use a MIME module.
|
||||
var contentType;
|
||||
if (filename.match(/\.js$/)) {
|
||||
contentType = "text/javascript";
|
||||
} else if (filename.match(/\.css$/)) {
|
||||
contentType = "text/css";
|
||||
} else if (filename.match(/\.html$/)) {
|
||||
contentType = "text/html";
|
||||
} else if (filename.match(/\.txt$/)) {
|
||||
contentType = "text/plain";
|
||||
} else if (filename.match(/\.png$/)) {
|
||||
contentType = "image/png";
|
||||
} else if (filename.match(/\.gif$/)) {
|
||||
contentType = "image/gif";
|
||||
} else if (filename.match(/\.ico$/)) {
|
||||
contentType = "image/x-icon";
|
||||
} else {
|
||||
contentType = "application/octet-stream";
|
||||
}
|
||||
|
||||
statFile(filename, function (error, date, exists) {
|
||||
if (date) {
|
||||
date = new Date(date);
|
||||
res.setHeader('last-modified', date.toUTCString());
|
||||
res.setHeader('date', (new Date()).toUTCString());
|
||||
if (server.maxAge) {
|
||||
var expiresDate = new Date((new Date()).getTime()+server.maxAge*1000);
|
||||
res.setHeader('expires', expiresDate.toUTCString());
|
||||
res.setHeader('cache-control', 'max-age=' + server.maxAge);
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
res.writeHead(500, {});
|
||||
>>>>>>> pita
|
||||
res.end();
|
||||
} else if (!exists) {
|
||||
res.writeHead(404, {});
|
||||
res.end();
|
||||
} else if (new Date(req.headers['if-modified-since']) >= date) {
|
||||
res.writeHead(304, {});
|
||||
res.end();
|
||||
} else {
|
||||
if (req.method == 'HEAD') {
|
||||
res.header("Content-Type", contentType);
|
||||
res.writeHead(200, {});
|
||||
res.end();
|
||||
} else if (req.method == 'GET') {
|
||||
getFileCompressed(filename, contentType, function (error, content) {
|
||||
if(ERR(error)) return;
|
||||
res.header("Content-Type", contentType);
|
||||
res.writeHead(200, {});
|
||||
res.write(content);
|
||||
res.end();
|
||||
});
|
||||
} else {
|
||||
res.writeHead(405, {'allow': 'HEAD, GET'});
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// find all includes in ace.js and embed them.
|
||||
function getAceFile(callback) {
|
||||
fs.readFile(ROOT_DIR + 'js/ace.js', "utf8", function(err, data) {
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
// Find all includes in ace.js and embed them
|
||||
var founds = data.match(/\$\$INCLUDE_[a-zA-Z_]+\("[^"]*"\)/gi);
|
||||
if (!settings.minify) {
|
||||
founds = [];
|
||||
}
|
||||
// Always include the require kernel.
|
||||
founds.push('$$INCLUDE_JS("../static/js/require-kernel.js")');
|
||||
|
||||
data += ';\n';
|
||||
data += 'Ace2Editor.EMBEDED = Ace2Editor.EMBEDED || {};\n';
|
||||
|
||||
// Request the contents of the included file on the server-side and write
|
||||
// them into the file.
|
||||
async.forEach(founds, function (item, callback) {
|
||||
var filename = item.match(/"([^"]*)"/)[1];
|
||||
var request = require('request');
|
||||
|
||||
var baseURI = 'http://localhost:' + settings.port
|
||||
|
||||
request(baseURI + path.normalize(path.join('/static/', filename)), function (error, response, body) {
|
||||
if (!error && response.statusCode == 200) {
|
||||
data += 'Ace2Editor.EMBEDED[' + JSON.stringify(filename) + '] = '
|
||||
+ JSON.stringify(body || '') + ';\n';
|
||||
} else {
|
||||
// Silence?
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function(error) {
|
||||
callback(error, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Check for the existance of the file and get the last modification date.
|
||||
function statFile(filename, callback) {
|
||||
if (filename == 'js/ace.js') {
|
||||
// Sometimes static assets are inlined into this file, so we have to stat
|
||||
// everything.
|
||||
lastModifiedDateOfEverything(function (error, date) {
|
||||
callback(error, date, !error);
|
||||
});
|
||||
} else if (filename == 'js/require-kernel.js') {
|
||||
callback(null, requireLastModified(), true);
|
||||
} else {
|
||||
fs.stat(ROOT_DIR + filename, function (error, stats) {
|
||||
if (error) {
|
||||
if (error.code == "ENOENT") {
|
||||
// Stat the directory instead.
|
||||
fs.stat(path.dirname(ROOT_DIR + filename), function (error, stats) {
|
||||
if (error) {
|
||||
if (error.code == "ENOENT") {
|
||||
callback(null, null, false);
|
||||
} else {
|
||||
callback(error);
|
||||
}
|
||||
} else {
|
||||
callback(null, stats.mtime.getTime(), false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback(error);
|
||||
}
|
||||
} else {
|
||||
callback(null, stats.mtime.getTime(), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function lastModifiedDateOfEverything(callback) {
|
||||
var folders2check = [ROOT_DIR + 'js/', ROOT_DIR + 'css/'];
|
||||
var latestModification = 0;
|
||||
//go trough this two folders
|
||||
async.forEach(folders2check, function(path, callback)
|
||||
{
|
||||
//read the files in the folder
|
||||
fs.readdir(path, function(err, files)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//we wanna check the directory itself for changes too
|
||||
files.push(".");
|
||||
|
||||
//go trough all files in this folder
|
||||
async.forEach(files, function(filename, callback)
|
||||
{
|
||||
//get the stat data of this file
|
||||
fs.stat(path + "/" + filename, function(err, stats)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//get the modification time
|
||||
var modificationTime = stats.mtime.getTime();
|
||||
|
||||
//compare the modification time to the highest found
|
||||
if(modificationTime > latestModification)
|
||||
{
|
||||
latestModification = modificationTime;
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}, callback);
|
||||
});
|
||||
}, function () {
|
||||
callback(null, latestModification);
|
||||
});
|
||||
}
|
||||
|
||||
// This should be provided by the module, but until then, just use startup
|
||||
// time.
|
||||
var _requireLastModified = new Date();
|
||||
function requireLastModified() {
|
||||
return _requireLastModified.toUTCString();
|
||||
}
|
||||
function requireDefinition() {
|
||||
return 'var require = ' + RequireKernel.kernelSource + ';\n';
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
function tarCode(jsFiles, write, callback) {
|
||||
write('require.define({');
|
||||
var initialEntry = true;
|
||||
async.forEach(jsFiles, function (filename, callback){
|
||||
var path;
|
||||
var srcPath;
|
||||
if (filename.indexOf('plugins/') == 0) {
|
||||
srcPath = filename.substring('plugins/'.length);
|
||||
path = require.resolve(srcPath);
|
||||
} else {
|
||||
srcPath = '/' + filename;
|
||||
path = JS_DIR + filename;
|
||||
}
|
||||
|
||||
srcPath = JSON.stringify(srcPath);
|
||||
var srcPathAbbv = JSON.stringify(srcPath.replace(/\.js$/, ''));
|
||||
|
||||
if (filename == 'ace.js') {
|
||||
getAceFile(handleFile);
|
||||
} else {
|
||||
fs.readFile(path, "utf8", handleFile);
|
||||
}
|
||||
|
||||
function handleFile(err, data) {
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
if (!initialEntry) {
|
||||
write('\n,');
|
||||
} else {
|
||||
initialEntry = false;
|
||||
}
|
||||
write(srcPath + ': ')
|
||||
data = '(function (require, exports, module) {' + data + '})';
|
||||
=======
|
||||
function getFileCompressed(filename, contentType, callback) {
|
||||
getFile(filename, function (error, content) {
|
||||
if (error || !content) {
|
||||
callback(error, content);
|
||||
} else {
|
||||
>>>>>>> pita
|
||||
if (settings.minify) {
|
||||
if (contentType == 'text/javascript') {
|
||||
try {
|
||||
content = compressJS([content]);
|
||||
} catch (error) {
|
||||
// silence
|
||||
}
|
||||
} else if (contentType == 'text/css') {
|
||||
content = compressCSS([content]);
|
||||
}
|
||||
}
|
||||
callback(null, content);
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
}, function (err) {
|
||||
if(ERR(err, callback)) return;
|
||||
write('});\n');
|
||||
callback();
|
||||
=======
|
||||
>>>>>>> pita
|
||||
});
|
||||
}
|
||||
|
||||
function getFile(filename, callback) {
|
||||
if (filename == 'js/ace.js') {
|
||||
getAceFile(callback);
|
||||
} else if (filename == 'js/require-kernel.js') {
|
||||
callback(undefined, requireDefinition());
|
||||
} else {
|
||||
fs.readFile(ROOT_DIR + filename, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function compressJS(values)
|
||||
{
|
||||
var complete = values.join("\n");
|
||||
var ast = jsp.parse(complete); // parse code and get the initial AST
|
||||
ast = pro.ast_mangle(ast); // get a new AST with mangled names
|
||||
ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
|
||||
return pro.gen_code(ast); // compressed code here
|
||||
}
|
||||
|
||||
function compressCSS(values)
|
||||
{
|
||||
var complete = values.join("\n");
|
||||
return cleanCSS.process(complete);
|
||||
}
|
|
@ -23,6 +23,10 @@ var fs = require("fs");
|
|||
var os = require("os");
|
||||
var path = require('path');
|
||||
var argv = require('./Cli').argv;
|
||||
var npm = require("npm/lib/npm.js");
|
||||
|
||||
/* Root path of the installation */
|
||||
exports.root = path.normalize(path.join(npm.dir, ".."));
|
||||
|
||||
/**
|
||||
* The IP ep-lite should listen to
|
||||
|
@ -40,7 +44,7 @@ exports.dbType = "dirty";
|
|||
/**
|
||||
* This setting is passed with dbType to ueberDB to set up the database
|
||||
*/
|
||||
exports.dbSettings = { "filename" : "../var/dirty.db" };
|
||||
exports.dbSettings = { "filename" : path.join(exports.root, "var/dirty.db") };
|
||||
/**
|
||||
* The default Text of a new pad
|
||||
*/
|
||||
|
@ -96,10 +100,12 @@ exports.abiwordAvailable = function()
|
|||
|
||||
// Discover where the settings file lives
|
||||
var settingsFilename = argv.settings || "settings.json";
|
||||
var settingsPath = settingsFilename.charAt(0) == '/' ? '' : path.normalize(__dirname + "/../../");
|
||||
if (settingsFilename.charAt(0) != '/') {
|
||||
settingsFilename = path.normalize(path.join(root, settingsFilename));
|
||||
}
|
||||
|
||||
//read the settings sync
|
||||
var settingsStr = fs.readFileSync(settingsPath + settingsFilename).toString();
|
||||
var settingsStr = fs.readFileSync(settingsFilename).toString();
|
||||
|
||||
//remove all comments
|
||||
settingsStr = settingsStr.replace(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/gm,"").replace(/#.*/g,"").replace(/\/\/.*/g,"");
|
|
@ -23,7 +23,9 @@ var zlib = require('zlib');
|
|||
var util = require('util');
|
||||
|
||||
var ROOT_DIR = path.normalize(__dirname + "/../");
|
||||
var CACHE_DIR = ROOT_DIR + '../var/';
|
||||
var CACHE_DIR = path.normalize(ROOT_DIR + '../../var/');
|
||||
console.log(CACHE_DIR)
|
||||
CACHE_DIR = path.existsSync(CACHE_DIR) ? CACHE_DIR : undefined;
|
||||
|
||||
var responseCache = {};
|
||||
|
||||
|
@ -37,7 +39,7 @@ function CachingMiddleware() {
|
|||
}
|
||||
CachingMiddleware.prototype = new function () {
|
||||
function handle(req, res, next) {
|
||||
if (!(req.method == "GET" || req.method == "HEAD")) {
|
||||
if (!(req.method == "GET" || req.method == "HEAD") || !CACHE_DIR) {
|
||||
return next(undefined, req, res);
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
, "pad.js"
|
||||
, "ace2_common.js"
|
||||
, "pad_utils.js"
|
||||
, "plugins.js"
|
||||
, "undo-xpopup.js"
|
||||
, "json2.js"
|
||||
, "pad_cookie.js"
|
||||
|
@ -27,7 +26,6 @@
|
|||
, "timeslider.js": [
|
||||
"jquery.js"
|
||||
, "security.js"
|
||||
, "plugins.js"
|
||||
, "undo-xpopup.js"
|
||||
, "json2.js"
|
||||
, "colorutils.js"
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name" : "etherpad-lite",
|
||||
"name" : "ep_etherpad-lite",
|
||||
"description" : "A Etherpad based on node.js",
|
||||
"homepage" : "https://github.com/Pita/etherpad-lite",
|
||||
"keywords" : ["etherpad", "realtime", "collaborative", "editor"],
|
||||
|
@ -12,7 +12,7 @@
|
|||
"dependencies" : {
|
||||
"yajsml" : "1.1.2",
|
||||
"request" : "2.9.100",
|
||||
"require-kernel" : "1.0.3",
|
||||
"require-kernel" : "1.0.5",
|
||||
"socket.io" : "0.8.7",
|
||||
"ueberDB" : "0.1.7",
|
||||
"async" : "0.1.18",
|
||||
|
@ -22,7 +22,8 @@
|
|||
"formidable" : "1.0.9",
|
||||
"log4js" : "0.4.1",
|
||||
"jsdom-nocontextifiy" : "0.2.10",
|
||||
"async-stacktrace" : "0.0.2"
|
||||
"async-stacktrace" : "0.0.2",
|
||||
"npm" : "1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jshint" : "*"
|
|
@ -0,0 +1,3 @@
|
|||
*
|
||||
!.gitignore
|
||||
!*.template
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 697 B |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 1009 B After Width: | Height: | Size: 1009 B |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 494 B |
Before Width: | Height: | Size: 658 B After Width: | Height: | Size: 658 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 123 B After Width: | Height: | Size: 123 B |
Before Width: | Height: | Size: 131 B After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 182 B After Width: | Height: | Size: 182 B |
Before Width: | Height: | Size: 686 B After Width: | Height: | Size: 686 B |
Before Width: | Height: | Size: 517 B After Width: | Height: | Size: 517 B |
|
@ -25,7 +25,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var AttributePoolFactory = require("/AttributePoolFactory");
|
||||
var AttributePoolFactory = require("./AttributePoolFactory");
|
||||
|
||||
var _opt = null;
|
||||
|
|
@ -28,7 +28,7 @@ Ace2Editor.registry = {
|
|||
nextId: 1
|
||||
};
|
||||
|
||||
var plugins = require('/plugins').plugins;
|
||||
var hooks = require('./pluginfw/hooks');
|
||||
|
||||
function Ace2Editor()
|
||||
{
|
||||
|
@ -156,7 +156,11 @@ function Ace2Editor()
|
|||
}
|
||||
function pushRequireScriptTo(buffer) {
|
||||
var KERNEL_SOURCE = '../static/js/require-kernel.js';
|
||||
var KERNEL_BOOT = 'require.setRootURI("../minified/");\nrequire.setGlobalKeyPath("require");'
|
||||
var KERNEL_BOOT = '\
|
||||
require.setRootURI("../javascripts/src");\n\
|
||||
require.setLibraryURI("../javascripts/lib");\n\
|
||||
require.setGlobalKeyPath("require");\n\
|
||||
';
|
||||
if (Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[KERNEL_SOURCE]) {
|
||||
buffer.push('<script type="text/javascript">');
|
||||
buffer.push(Ace2Editor.EMBEDED[KERNEL_SOURCE]);
|
||||
|
@ -166,17 +170,18 @@ function Ace2Editor()
|
|||
}
|
||||
function pushScriptsTo(buffer) {
|
||||
/* Folling is for packaging regular expression. */
|
||||
/* $$INCLUDE_JS("../minified/ace2_inner.js?callback=require.define"); */
|
||||
var ACE_SOURCE = '../minified/ace2_inner.js?callback=require.define';
|
||||
/* $$INCLUDE_JS("../javascripts/src/ace2_inner.js?callback=require.define"); */
|
||||
var ACE_SOURCE = '../javascripts/src/ace2_inner.js?callback=require.define';
|
||||
if (Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[ACE_SOURCE]) {
|
||||
buffer.push('<script type="text/javascript">');
|
||||
buffer.push(Ace2Editor.EMBEDED[ACE_SOURCE]);
|
||||
buffer.push('require("/ace2_inner");');
|
||||
buffer.push('require("ep_etherpad-lite/static/js/ace2_inner");');
|
||||
buffer.push('<\/script>');
|
||||
} else {
|
||||
file = ACE_SOURCE;
|
||||
buffer.push('<script type="application/javascript" src="' + ACE_SOURCE + '"><\/script>');
|
||||
buffer.push('<script type="text/javascript">');
|
||||
buffer.push('require("/ace2_inner");');
|
||||
buffer.push('require("ep_etherpad-lite/static/js/ace2_inner");');
|
||||
buffer.push('<\/script>');
|
||||
}
|
||||
}
|
||||
|
@ -232,7 +237,7 @@ function Ace2Editor()
|
|||
for (var i = 0, ii = iframeHTML.length; i < ii; i++) {
|
||||
iframeHTML[i] = JSON.stringify(iframeHTML[i]);
|
||||
}
|
||||
plugins.callHook("aceInitInnerdocbodyHead", {
|
||||
hooks.callAll("aceInitInnerdocbodyHead", {
|
||||
iframeHTML: iframeHTML
|
||||
});
|
||||
for (var i = 0, ii = iframeHTML.length; i < ii; i++) {
|
||||
|
@ -258,7 +263,7 @@ function Ace2Editor()
|
|||
<script type="text/javascript">\
|
||||
require.define("/plugins", null);\n\
|
||||
require.define("/plugins.js", function (require, exports, module) {\
|
||||
module.exports = parent.parent.require("/plugins");\
|
||||
module.exports = require("ep_etherpad-lite/static/js/plugins");\
|
||||
});\
|
||||
</script>\
|
||||
');
|
||||
|
@ -271,7 +276,7 @@ function Ace2Editor()
|
|||
var thisFunctionsName = "ChildAccessibleAce2Editor";
|
||||
(function () {return this}())[thisFunctionsName] = Ace2Editor;
|
||||
|
||||
var outerScript = 'editorId = "' + info.id + '"; editorInfo = parent.' + thisFunctionsName + '.registry[editorId]; ' + 'window.onload = function() ' + '{ window.onload = null; setTimeout' + '(function() ' + '{ var iframe = document.createElement("IFRAME"); ' + 'iframe.scrolling = "no"; var outerdocbody = document.getElementById("outerdocbody"); ' + 'iframe.frameBorder = 0; iframe.allowTransparency = true; ' + // for IE
|
||||
var outerScript = 'editorId = "' + info.id + '"; editorInfo = parent.' + thisFunctionsName + '.registry[editorId]; ' + 'window.onload = function() ' + '{ window.onload = null; setTimeout' + '(function() ' + '{ var iframe = document.createElement("IFRAME"); iframe.name = "ace_inner";' + 'iframe.scrolling = "no"; var outerdocbody = document.getElementById("outerdocbody"); ' + 'iframe.frameBorder = 0; iframe.allowTransparency = true; ' + // for IE
|
||||
'outerdocbody.insertBefore(iframe, outerdocbody.firstChild); ' + 'iframe.ace_outerWin = window; ' + 'readyFunc = function() { editorInfo.onEditorReady(); readyFunc = null; editorInfo = null; }; ' + 'var doc = iframe.contentWindow.document; doc.open(); var text = (' + JSON.stringify(iframeHTML.join('\n')) + ');doc.write(text); doc.close(); ' + '}, 0); }';
|
||||
|
||||
var outerHTML = [doctype, '<html><head>']
|
||||
|
@ -288,6 +293,7 @@ function Ace2Editor()
|
|||
outerHTML.push('<link rel="stylesheet" type="text/css" href="data:text/css,"/>', '\x3cscript>\n', outerScript.replace(/<\//g, '<\\/'), '\n\x3c/script>', '</head><body id="outerdocbody"><div id="sidediv"><!-- --></div><div id="linemetricsdiv">x</div><div id="overlaysdiv"><!-- --></div></body></html>');
|
||||
|
||||
var outerFrame = document.createElement("IFRAME");
|
||||
outerFrame.name = "ace_outer";
|
||||
outerFrame.frameBorder = 0; // for IE
|
||||
info.frame = outerFrame;
|
||||
document.getElementById(containerId).appendChild(outerFrame);
|
|
@ -20,7 +20,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var Security = require('/security');
|
||||
var Security = require('./security');
|
||||
|
||||
function isNodeText(node)
|
||||
{
|
|
@ -20,7 +20,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var Ace2Common = require('/ace2_common');
|
||||
var Ace2Common = require('./ace2_common');
|
||||
|
||||
// Extract useful method defined in the other module.
|
||||
var isNodeText = Ace2Common.isNodeText;
|
||||
|
@ -38,18 +38,17 @@ var htmlPrettyEscape = Ace2Common.htmlPrettyEscape;
|
|||
var map = Ace2Common.map;
|
||||
var noop = Ace2Common.noop;
|
||||
|
||||
var makeChangesetTracker = require('/changesettracker').makeChangesetTracker;
|
||||
var colorutils = require('/colorutils').colorutils;
|
||||
var makeContentCollector = require('/contentcollector').makeContentCollector;
|
||||
var makeCSSManager = require('/cssmanager').makeCSSManager;
|
||||
var domline = require('/domline').domline;
|
||||
var AttribPool = require('/AttributePoolFactory').createAttributePool;
|
||||
var Changeset = require('/Changeset');
|
||||
var linestylefilter = require('/linestylefilter').linestylefilter;
|
||||
var newSkipList = require('/skiplist').newSkipList;
|
||||
var undoModule = require('/undomodule').undoModule;
|
||||
var makeVirtualLineView = require('/virtual_lines').makeVirtualLineView;
|
||||
|
||||
var makeChangesetTracker = require('./changesettracker').makeChangesetTracker;
|
||||
var colorutils = require('./colorutils').colorutils;
|
||||
var makeContentCollector = require('./contentcollector').makeContentCollector;
|
||||
var makeCSSManager = require('./cssmanager').makeCSSManager;
|
||||
var domline = require('./domline').domline;
|
||||
var AttribPool = require('./AttributePoolFactory').createAttributePool;
|
||||
var Changeset = require('./Changeset');
|
||||
var linestylefilter = require('./linestylefilter').linestylefilter;
|
||||
var newSkipList = require('./skiplist').newSkipList;
|
||||
var undoModule = require('./undomodule').undoModule;
|
||||
var makeVirtualLineView = require('./virtual_lines').makeVirtualLineView;
|
||||
|
||||
function Ace2Inner(){
|
||||
var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;"
|
|
@ -20,12 +20,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var makeCSSManager = require('/cssmanager').makeCSSManager;
|
||||
var domline = require('/domline').domline;
|
||||
var AttribPool = require('/AttributePoolFactory').createAttributePool;
|
||||
var Changeset = require('/Changeset');
|
||||
var linestylefilter = require('/linestylefilter').linestylefilter;
|
||||
var colorutils = require('/colorutils').colorutils;
|
||||
var makeCSSManager = require('./cssmanager').makeCSSManager;
|
||||
var domline = require('./domline').domline;
|
||||
var AttribPool = require('./AttributePoolFactory').createAttributePool;
|
||||
var Changeset = require('./Changeset');
|
||||
var linestylefilter = require('./linestylefilter').linestylefilter;
|
||||
var colorutils = require('./colorutils').colorutils;
|
||||
var Ace2Common = require('./ace2_common');
|
||||
|
||||
var map = Ace2Common.map;
|
|
@ -20,8 +20,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var AttribPool = require('/AttributePoolFactory').createAttributePool;
|
||||
var Changeset = require('/Changeset');
|
||||
var AttribPool = require('./AttributePoolFactory').createAttributePool;
|
||||
var Changeset = require('./Changeset');
|
||||
|
||||
function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
||||
{
|
|
@ -20,8 +20,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var padutils = require('/pad_utils').padutils;
|
||||
var padcookie = require('/pad_cookie').padcookie;
|
||||
var padutils = require('./pad_utils').padutils;
|
||||
var padcookie = require('./pad_cookie').padcookie;
|
||||
|
||||
var chat = (function()
|
||||
{
|
|
@ -20,7 +20,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var chat = require('/chat').chat;
|
||||
var chat = require('./chat').chat;
|
||||
|
||||
// Dependency fill on init. This exists for `pad.socket` only.
|
||||
// TODO: bind directly to the socket.
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
var _MAX_LIST_LEVEL = 8;
|
||||
|
||||
var Changeset = require('/Changeset');
|
||||
var plugins = require('/plugins').plugins;
|
||||
var Changeset = require('./Changeset');
|
||||
var hooks = require('./pluginfw/hooks');
|
||||
|
||||
function sanitizeUnicode(s)
|
||||
{
|
||||
|
@ -37,8 +37,6 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
{
|
||||
browser = browser || {};
|
||||
|
||||
var plugins_ = plugins;
|
||||
|
||||
var dom = domInterface || {
|
||||
isNodeText: function(n)
|
||||
{
|
||||
|
@ -448,7 +446,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
var oldAuthorOrNull = null;
|
||||
if (collectStyles)
|
||||
{
|
||||
plugins_.callHook('collectContentPre', {
|
||||
hooks.callAll('collectContentPre', {
|
||||
cc: cc,
|
||||
state: state,
|
||||
tname: tname,
|
||||
|
@ -510,7 +508,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
|
||||
if (collectStyles)
|
||||
{
|
||||
plugins_.callHook('collectContentPost', {
|
||||
hooks.callAll('collectContentPost', {
|
||||
cc: cc,
|
||||
state: state,
|
||||
tname: tname,
|
|
@ -26,9 +26,9 @@
|
|||
// requires: plugins
|
||||
// requires: undefined
|
||||
|
||||
var Security = require('/security');
|
||||
var Ace2Common = require('/ace2_common');
|
||||
var plugins = require('/plugins').plugins;
|
||||
var Security = require('./security');
|
||||
var hooks = require('./pluginfw/hooks');
|
||||
var Ace2Common = require('./ace2_common');
|
||||
var map = Ace2Common.map;
|
||||
var noop = Ace2Common.noop;
|
||||
var identity = Ace2Common.identity;
|
||||
|
@ -142,9 +142,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
var extraOpenTags = "";
|
||||
var extraCloseTags = "";
|
||||
|
||||
var plugins_ = plugins;
|
||||
|
||||
map(plugins_.callHook("aceCreateDomLine", {
|
||||
map(hooks.callAll("aceCreateDomLine", {
|
||||
domline: domline,
|
||||
cls: cls
|
||||
}), function(modifier)
|