Commit 24b0712d authored by Stefan's avatar Stefan
Browse files

Merge new release into master branch!

parents cc34f4e3 64d94cb3
......@@ -2,6 +2,7 @@ node_modules
settings.json
!settings.json.template
APIKEY.txt
SESSIONKEY.txt
bin/abiword.exe
bin/node.exe
etherpad-lite-win.zip
......
# 1.5.5
* SECURITY: Also don't allow read files on directory traversal on minify paths
* NEW: padOptions can be set in settings.json now
* Fix: Add check for special characters in createPad API function
* Fix: Middle click on a link in firefox don't paste text anymore
* Fix: Made setPadRaw async to import larger etherpad files
* Fix: rtl
* Fix: Problem in older IEs
* Other: Update to express 4.x
* Other: Dropped support for node 0.8
* Other: Update ejs to version 2.x
* Other: Moved sessionKey from settings.json to a new auto-generated SESSIONKEY.txt file
# 1.5.4
* SECURITY: Also don't allow read files on directory traversal on frontend tests path
......
......@@ -22,7 +22,7 @@ Also, check out the **[FAQ](https://github.com/ether/etherpad-lite/wiki/FAQ)**,
# Installation
Etherpad works with node v0.8, v0.10 and v0.11, only. (We don't support v0.6)
Etherpad works with node v0.10+ and io.js.
## Windows
......
#!/bin/sh
NODE_VERSION="0.8.4"
NODE_VERSION="0.10.38"
#Move to the folder where ep-lite is installed
cd `dirname $0`
......
......@@ -50,9 +50,9 @@ NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2)
if hash iojs 2>/dev/null; then
IOJS_VERSION=$(iojs --version)
fi
if [ ! $NODE_V_MINOR = "v0.8" ] && [ ! $NODE_V_MINOR = "v0.10" ] && [ ! $NODE_V_MINOR = "v0.11" ] && [ ! $NODE_V_MINOR = "v0.12" ]; then
if [ ! $NODE_V_MINOR = "v0.10" ] && [ ! $NODE_V_MINOR = "v0.11" ] && [ ! $NODE_V_MINOR = "v0.12" ]; then
if [ ! $IOJS_VERSION ]; then
echo "You're running a wrong version of node, or io.js is not installed. You're using $NODE_VERSION, we need v0.8.x, v0.10.x, v0.11.x or v0.12.x" >&2
echo "You're running a wrong version of node, or io.js is not installed. You're using $NODE_VERSION, we need v0.10.x, v0.11.x or v0.12.x" >&2
exit 1
fi
fi
......
......@@ -8,7 +8,7 @@ cmd /C node -e "" || ( echo "Please install node.js ( http://nodejs.org )" && ex
echo _
echo Checking node version...
set check_version="if(['8','10'].indexOf(process.version.split('.')[1].toString()) === -1) { console.log('You are running a wrong version of Node. Etherpad requires v0.8.x or v0.10.x'); process.exit(1) }"
set check_version="if(['10','11','12'].indexOf(process.version.split('.')[1]) === -1 && process.version.split('.')[0] !== '1') { console.log('You are running a wrong version of Node. Etherpad requires v0.10+'); process.exit(1) }"
cmd /C node -e %check_version% || exit /B 1
echo _
......
......@@ -61,7 +61,7 @@ Portal submits content into new blog post
## Usage
### API version
The latest version is `1.2.11`
The latest version is `1.2.12`
The current version can be queried via /api.
......@@ -232,7 +232,7 @@ creates a new session. validUntil is an unix timestamp in seconds
deletes a session
*Example returns:*
* `{code: 1, message:"ok", data: null}`
* `{code: 0, message:"ok", data: null}`
* `{code: 1, message:"sessionID does not exist", data: null}`
#### getSessionInfo(sessionID)
......@@ -388,10 +388,12 @@ Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security
* API >= 1
creates a new (non-group) pad. Note that if you need to create a group Pad, you should call **createGroupPad**.
You get an error message if you use one of the following characters in the padID: "/", "?", "&" or "#".
*Example returns:*
* `{code: 0, message:"ok", data: null}`
* `{code: 1, message:"pad does already exist", data: null}`
* `{code: 1, message:"padID does already exist", data: null}`
* `{code: 1, message:"malformed padID: Remove special characters", data: null}`
#### getRevisionsCount(padID)
* API >= 1
......
......@@ -15,10 +15,6 @@
"ip": "0.0.0.0",
"port" : 9001,
// Session Key, used for reconnecting user sessions
// Set this to a secure string at least 10 characters long. Do not share this value.
"sessionKey" : "",
/*
// Node native SSL support
// this is disabled by default
......@@ -53,6 +49,21 @@
//the default text of a pad
"defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n",
/* Default Pad behavior, users can override by changing */
"padOptions": {
"noColors": false,
"showControls": true,
"showChat": true,
"showLineNumbers": true,
"useMonospaceFont": false,
"userName": false,
"userColor": false,
"rtl": false,
"alwaysShowChat": false,
"chatAndUsers": false,
"lang": "en-gb"
},
/* Shoud we suppress errors from being visible in the default Pad Text? */
"suppressErrorsInPadText" : false,
......
......@@ -687,12 +687,21 @@ Example returns:
exports.createPad = function(padID, text, callback)
{
//ensure there is no $ in the padID
if(padID && padID.indexOf("$") != -1)
if(padID)
{
callback(new customError("createPad can't create group pads","apierror"));
return;
if(padID.indexOf("$") != -1)
{
callback(new customError("createPad can't create group pads","apierror"));
return;
}
//check for url special characters
else if(padID.match(/(\/|\?|&|#)/))
{
callback(new customError("malformed padID: Remove special characters","apierror"));
return;
}
}
//create pad
getPadSafe(padID, false, text, function(err)
{
......
......@@ -4,7 +4,7 @@
* This is not used for authors that are created via the API at current
*/
var Store = require('ep_etherpad-lite/node_modules/connect/lib/middleware/session/store'),
var Store = require('ep_etherpad-lite/node_modules/express-session').Store,
db = require('ep_etherpad-lite/node/db/DB').db,
log4js = require('ep_etherpad-lite/node_modules/log4js'),
messageLogger = log4js.getLogger("SessionStore");
......
......@@ -26,7 +26,7 @@ var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks.js");
var resolve = require("resolve");
exports.info = {
buf_stack: [],
__output_stack: [],
block_stack: [],
file_stack: [],
args: []
......@@ -41,27 +41,27 @@ function createBlockId(name) {
}
exports._init = function (b, recursive) {
exports.info.buf_stack.push(exports.info.buf);
exports.info.buf = b;
exports.info.__output_stack.push(exports.info.__output);
exports.info.__output = b;
}
exports._exit = function (b, recursive) {
getCurrentFile().inherit.forEach(function (item) {
exports._require(item.name, item.args);
});
exports.info.buf = exports.info.buf_stack.pop();
exports.info.__output = exports.info.__output_stack.pop();
}
exports.begin_capture = function() {
exports.info.buf_stack.push(exports.info.buf.concat());
exports.info.buf.splice(0, exports.info.buf.length);
exports.info.__output_stack.push(exports.info.__output.concat());
exports.info.__output.splice(0, exports.info.__output.length);
}
exports.end_capture = function () {
var res = exports.info.buf.join("");
exports.info.buf.splice.apply(
exports.info.buf,
[0, exports.info.buf.length].concat(exports.info.buf_stack.pop()));
var res = exports.info.__output.join("");
exports.info.__output.splice.apply(
exports.info.__output,
[0, exports.info.__output.length].concat(exports.info.__output_stack.pop()));
return res;
}
......@@ -80,7 +80,7 @@ exports.end_block = function () {
var renderContext = exports.info.args[exports.info.args.length-1];
var args = {content: exports.end_define_block(), renderContext: renderContext};
hooks.callAll("eejsBlock_" + name, args);
exports.info.buf.push(args.content);
exports.info.__output.push(args.content);
}
exports.begin_block = exports.begin_define_block;
......@@ -114,7 +114,7 @@ exports.require = function (name, args, mod) {
args.e = exports;
args.require = require;
var template = '<% e._init(buf); %>' + fs.readFileSync(ejspath).toString() + '<% e._exit(); %>';
var template = '<% e._init(__output); %>' + fs.readFileSync(ejspath).toString() + '<% e._exit(); %>';
exports.info.args.push(args);
exports.info.file_stack.push({path: ejspath, inherit: []});
......@@ -127,5 +127,5 @@ exports.require = function (name, args, mod) {
}
exports._require = function (name, args) {
exports.info.buf.push(exports.require(name, args));
exports.info.__output.push(exports.require(name, args));
}
......@@ -103,7 +103,7 @@ exports.doExport = function(req, res, padId, type)
//send the file
function(callback)
{
res.sendfile(destFile, null, callback);
res.sendFile(destFile, null, callback);
},
//clean up temporary files
function(callback)
......@@ -184,7 +184,7 @@ exports.doExport = function(req, res, padId, type)
//send the file
function(callback)
{
res.sendfile(destFile, null, callback);
res.sendFile(destFile, null, callback);
},
//clean up temporary files
function(callback)
......
......@@ -113,10 +113,8 @@ exports.doImport = function(req, res, padId)
if(ERR(err, callback)) return callback();
if(result.length > 0){ // This feels hacky and wrong..
importHandledByPlugin = true;
callback();
}else{
callback();
}
callback();
});
},
function(callback) {
......@@ -145,7 +143,7 @@ exports.doImport = function(req, res, padId)
},
//convert file to html
function(callback) {
if(!importHandledByPlugin || !directDatabaseAccess){
if(!importHandledByPlugin && !directDatabaseAccess){
var fileEnding = path.extname(srcFile).toLowerCase();
var fileIsHTML = (fileEnding === ".html" || fileEnding === ".htm");
var fileIsTXT = (fileEnding === ".txt");
......@@ -171,28 +169,24 @@ exports.doImport = function(req, res, padId)
},
function(callback) {
if (!abiword){
if(!directDatabaseAccess) {
// Read the file with no encoding for raw buffer access.
fs.readFile(destFile, function(err, buf) {
if (err) throw err;
var isAscii = true;
// Check if there are only ascii chars in the uploaded file
for (var i=0, len=buf.length; i<len; i++) {
if (buf[i] > 240) {
isAscii=false;
break;
}
if (!abiword && !directDatabaseAccess){
// Read the file with no encoding for raw buffer access.
fs.readFile(destFile, function(err, buf) {
if (err) throw err;
var isAscii = true;
// Check if there are only ascii chars in the uploaded file
for (var i=0, len=buf.length; i<len; i++) {
if (buf[i] > 240) {
isAscii=false;
break;
}
if (isAscii) {
callback();
} else {
callback("uploadFailed");
}
});
}else{
callback();
}
}
if (isAscii) {
callback();
} else {
callback("uploadFailed");
}
});
} else {
callback();
}
......@@ -303,7 +297,7 @@ exports.doImport = function(req, res, padId)
var impexp = window.parent.padimpexp.handleFrameCall('" + directDatabaseAccess +"', '" + status + "'); \
}) \
</script>"
, 200);
);
});
}
......@@ -1182,6 +1182,7 @@ function handleClientReady(client, message)
"userIsGuest": true,
"userColor": authorColorId,
"padId": message.padId,
"padOptions": settings.padOptions,
"initialTitle": "Pad: " + message.padId,
"opts": {},
// tell the client the number of the latest chat-message, which will be
......
......@@ -69,10 +69,8 @@ exports.restartServer = function () {
if(settings.trustProxy){
app.enable('trust proxy');
}
app.configure(function() {
hooks.callAll("expressConfigure", {"app": app});
});
hooks.callAll("expressConfigure", {"app": app});
hooks.callAll("expressCreateServer", {"app": app, "server": server});
server.listen(settings.port, settings.ip);
......
......@@ -39,7 +39,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
// if an error occurs Connect will pass it down
// through these "error-handling" middleware
// allowing you to respond however you like
res.send(500, { error: 'Sorry, something bad happened!' });
res.status(500).send({ error: 'Sorry, something bad happened!' });
console.error(err.stack? err.stack : err.toString());
stats.meter('http500').mark()
})
......@@ -50,4 +50,4 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//https://github.com/joyent/node/issues/1553
process.on('SIGINT', exports.gracefulShutdown);
}
}
\ No newline at end of file
}
......@@ -55,7 +55,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
ERR(err);
if(err == "notfound")
res.send(404, '404 - Not Found');
res.status(404).send('404 - Not Found');
else
res.send(html);
});
......
......@@ -7,7 +7,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//ensure the padname is valid and the url doesn't end with a /
if(!padManager.isValidPadId(padId) || /\/$/.test(req.url))
{
res.send(404, 'Such a padname is forbidden');
res.status(404).send('Such a padname is forbidden');
}
else
{
......@@ -19,7 +19,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
var query = url.parse(req.url).query;
if ( query ) real_url += '?' + query;
res.header('Location', real_url);
res.send(302, 'You should be redirected to <a href="' + real_url + '">' + real_url + '</a>');
res.status(302).send('You should be redirected to <a href="' + real_url + '">' + real_url + '</a>');
}
//the pad id was fine, so just render it
else
......
......@@ -6,7 +6,8 @@ var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess");
var padMessageHandler = require("../../handler/PadMessageHandler");
var connect = require('connect');
var cookieParser = require('cookie-parser');
var sessionModule = require('express-session');
exports.expressCreateServer = function (hook_name, args, cb) {
//init socket.io and redirect all requests to the MessageHandler
......@@ -20,6 +21,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
/* Require an express session cookie to be present, and load the
* session. See http://www.danielbaulig.de/socket-ioexpress for more
* info */
var cookieParserFn = cookieParser(webaccess.secret, {});
io.use(function(socket, accept) {
var data = socket.request;
......@@ -29,8 +31,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
}else{
if (!data.headers.cookie) return accept('No session cookie transmitted.', false);
}
// Use connect's cookie parser, because it knows how to parse signed cookies
connect.cookieParser(webaccess.secret)(data, {}, function(err){
cookieParserFn(data, {}, function(err){
if(err) {
console.error(err);
accept("Couldn't parse request cookies. ", false);
......@@ -40,7 +41,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
data.sessionID = data.signedCookies.express_sid;
args.app.sessionStore.get(data.sessionID, function (err, session) {
if (err || !session) return accept('Bad session / session has expired', false);
data.session = new connect.middleware.session.Session(data, session);
data.session = new sessionModule.Session(data, session);
accept(null, true);
});
});
......
......@@ -19,13 +19,13 @@ exports.expressCreateServer = function (hook_name, args, cb) {
args.app.get('/robots.txt', function(req, res)
{
var filePath = path.normalize(__dirname + "/../../../static/custom/robots.txt");
res.sendfile(filePath, function(err)
res.sendFile(filePath, function(err)
{
//there is no custom favicon, send the default robots.txt which dissallows all
if(err)
{
filePath = path.normalize(__dirname + "/../../../static/robots.txt");
res.sendfile(filePath);
res.sendFile(filePath);
}
});
});
......@@ -60,13 +60,13 @@ exports.expressCreateServer = function (hook_name, args, cb) {
args.app.get( /\/favicon.ico$/, function(req, res)
{
var filePath = path.normalize(__dirname + "/../../../static/custom/favicon.ico");
res.sendfile(filePath, function(err)
res.sendFile(filePath, function(err)
{
//there is no custom favicon, send the default favicon
if(err)
{
filePath = path.normalize(__dirname + "/../../../static/favicon.ico");
res.sendfile(filePath);
res.sendFile(filePath);
}
});
});
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment