mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-28 11:26:16 -04:00
merge develop back in
This commit is contained in:
commit
2cd280a44b
17 changed files with 136 additions and 98 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -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
|
||||
|
|
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,3 +1,19 @@
|
|||
# 1.5.6
|
||||
* Fix: Error on windows installations
|
||||
|
||||
# 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
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ Documentation can be found in `docs/`.
|
|||
# Development
|
||||
|
||||
## Things you should know
|
||||
Read this [git guide](http://learn.github.com/p/index.html) and watch this [video on getting started with Etherpad Development](http://youtu.be/67-Q26YH97E).
|
||||
Understand [git](https://training.github.com/) and watch this [video on getting started with Etherpad Development](http://youtu.be/67-Q26YH97E).
|
||||
|
||||
If you're new to node.js, start with Ryan Dahl's [Introduction to Node.js](http://youtu.be/jo_B4LTHi3I).
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
NODE_VERSION="0.10.38"
|
||||
NODE_VERSION="0.12.2"
|
||||
|
||||
#Move to the folder where ep-lite is installed
|
||||
cd `dirname $0`
|
||||
|
@ -56,8 +56,6 @@ echo "remove git history to reduce folder size"
|
|||
rm -rf .git/objects
|
||||
|
||||
echo "remove windows jsdom-nocontextify/test folder"
|
||||
rm -rf /tmp/etherpad-lite-win/node_modules/ep_etherpad-lite/node_modules/jsdom-nocontextifiy/test/
|
||||
rm -rf /tmp/etherpad-lite-win/src/node_modules/jsdom-nocontextifiy/test/
|
||||
rm -rf /tmp/etherpad-lite-win/src/node_modules/wd/node_modules/request/node_modules/form-data/node_modules/combined-stream/test
|
||||
rm -rf /tmp/etherpad-lite-win/src/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@ var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
|||
exports.getLineHTMLForExport = function (hook, context) {
|
||||
var header = _analyzeLine(context.attribLine, context.apool);
|
||||
if (header) {
|
||||
return "<" + header + ">" + context.lineContents + "</" + header + ">";
|
||||
return "<" + header + ">" + context.lineContent + "</" + header + ">";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -54,6 +50,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,
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -21,20 +21,11 @@ var db = require("../db/DB").db;
|
|||
exports.setPadRaw = function(padId, records, callback){
|
||||
records = JSON.parse(records);
|
||||
|
||||
// !! HACK !!
|
||||
// If you have a really large pad it will cause a Maximum Range Stack crash
|
||||
// This is a temporary patch for that so things are kept stable.
|
||||
var recordCount = Object.keys(records).length;
|
||||
if(recordCount >= 50000){
|
||||
console.warn("Etherpad file is too large to import.. We need to fix this. See https://github.com/ether/etherpad-lite/issues/2524");
|
||||
return callback("tooLarge", false);
|
||||
}
|
||||
|
||||
async.eachSeries(Object.keys(records), function(key, cb){
|
||||
var value = records[key]
|
||||
|
||||
if(!value){
|
||||
cb(); // null values are bad.
|
||||
return setImmediate(cb);
|
||||
}
|
||||
|
||||
// Author data
|
||||
|
@ -76,7 +67,7 @@ exports.setPadRaw = function(padId, records, callback){
|
|||
// Write the value to the server
|
||||
db.set(newKey, value);
|
||||
|
||||
cb();
|
||||
setImmediate(cb);
|
||||
}, function(){
|
||||
callback(null, true);
|
||||
});
|
||||
|
|
|
@ -144,8 +144,11 @@ function minify(req, res, next)
|
|||
|
||||
// No relative paths, especially if they may go up the file hierarchy.
|
||||
filename = path.normalize(path.join(ROOT_DIR, filename));
|
||||
filename = filename.replace(/\.\./g, '')
|
||||
|
||||
if (filename.indexOf(ROOT_DIR) == 0) {
|
||||
filename = filename.slice(ROOT_DIR.length);
|
||||
filename = filename.replace(/\\/g, '/')
|
||||
} else {
|
||||
res.writeHead(404, {});
|
||||
res.end();
|
||||
|
@ -166,7 +169,7 @@ function minify(req, res, next)
|
|||
var plugin = plugins.plugins[library];
|
||||
var pluginPath = plugin.package.realPath;
|
||||
filename = path.relative(ROOT_DIR, pluginPath + libraryPath);
|
||||
filename = filename.replace(/\\/g, '/'); // Windows (safe generally?)
|
||||
filename = filename.replace(/\\/g, '/'); // windows path fix
|
||||
} else if (LIBRARY_WHITELIST.indexOf(library) != -1) {
|
||||
// Go straight into node_modules
|
||||
// Avoid `require.resolve()`, since 'mustache' and 'mustache/index.js'
|
||||
|
|
|
@ -28,6 +28,7 @@ var jsonminify = require("jsonminify");
|
|||
var log4js = require("log4js");
|
||||
var randomString = require("./randomstring");
|
||||
var suppressDisableMsg = " -- To suppress these warning messages change suppressErrorsInPadText to true in your settings.json\n";
|
||||
var _ = require("underscore");
|
||||
|
||||
/* Root path of the installation */
|
||||
exports.root = path.normalize(path.join(npm.dir, ".."));
|
||||
|
@ -84,6 +85,23 @@ exports.dbSettings = { "filename" : path.join(exports.root, "dirty.db") };
|
|||
*/
|
||||
exports.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\nEtherpad on Github: http:\/\/j.mp/ep-lite\n";
|
||||
|
||||
/**
|
||||
* The default Pad Settings for a user (Can be overridden by changing the setting
|
||||
*/
|
||||
exports.padOptions = {
|
||||
"noColors": false,
|
||||
"showControls": true,
|
||||
"showChat": true,
|
||||
"showLineNumbers": true,
|
||||
"useMonospaceFont": false,
|
||||
"userName": false,
|
||||
"userColor": false,
|
||||
"rtl": false,
|
||||
"alwaysShowChat": false,
|
||||
"chatAndUsers": false,
|
||||
"lang": "en-gb"
|
||||
}
|
||||
|
||||
/**
|
||||
* The toolbar buttons and order.
|
||||
*/
|
||||
|
@ -255,7 +273,11 @@ exports.reloadSettings = function reloadSettings() {
|
|||
//or it's a settings hash, specific to a plugin
|
||||
if(exports[i] !== undefined || i.indexOf('ep_')==0)
|
||||
{
|
||||
exports[i] = settings[i];
|
||||
if (_.isObject(settings[i]) && !_.isArray(settings[i])) {
|
||||
exports[i] = _.defaults(settings[i], exports[i]);
|
||||
} else {
|
||||
exports[i] = settings[i];
|
||||
}
|
||||
}
|
||||
//this setting is unkown, output a warning and throw it away
|
||||
else
|
||||
|
@ -286,13 +308,15 @@ exports.reloadSettings = function reloadSettings() {
|
|||
}
|
||||
}
|
||||
|
||||
if(!exports.sessionKey){ // If the secretKey isn't set we also create yet another unique value here
|
||||
exports.sessionKey = randomString(32);
|
||||
var sessionWarning = "You need to set a sessionKey value in settings.json, this will allow your users to reconnect to your Etherpad Instance if your instance restarts";
|
||||
if(!exports.suppressErrorsInPadText){
|
||||
exports.defaultPadText = exports.defaultPadText + "\nWarning: " + sessionWarning + suppressDisableMsg;
|
||||
if (!exports.sessionKey) {
|
||||
try {
|
||||
exports.sessionKey = fs.readFileSync("./SESSIONKEY.txt","utf8");
|
||||
} catch(e) {
|
||||
exports.sessionKey = randomString(32);
|
||||
fs.writeFileSync("./SESSIONKEY.txt",exports.sessionKey,"utf8");
|
||||
}
|
||||
console.warn(sessionWarning);
|
||||
} else {
|
||||
console.warn("Declaring the sessionKey in the settings.json is deprecated. This value is auto-generated now. Please remove the setting from the file.");
|
||||
}
|
||||
|
||||
if(exports.dbType === "dirty"){
|
||||
|
|
|
@ -56,5 +56,5 @@
|
|||
"repository" : { "type" : "git",
|
||||
"url" : "http://github.com/ether/etherpad-lite.git"
|
||||
},
|
||||
"version" : "1.5.4"
|
||||
"version" : "1.5.6"
|
||||
}
|
||||
|
|
|
@ -1920,7 +1920,11 @@ function Ace2Inner(){
|
|||
if (charsLeft === 0)
|
||||
{
|
||||
var index = 0;
|
||||
browser.msie = false; // Temp fix to resolve enter and backspace issues..
|
||||
|
||||
if (browser.msie && parseInt(browser.version) >= 11) {
|
||||
browser.msie = false; // Temp fix to resolve enter and backspace issues..
|
||||
// Note that this makes MSIE behave like modern browsers..
|
||||
}
|
||||
if (browser.msie && line == (rep.lines.length() - 1) && lineNode.childNodes.length === 0)
|
||||
{
|
||||
// best to stay at end of last empty div in IE
|
||||
|
|
|
@ -681,9 +681,9 @@ window.html10n = (function(window, document, undefined) {
|
|||
// Expand two-part locale specs
|
||||
var i=0
|
||||
langs.forEach(function(lang) {
|
||||
if(!lang) return
|
||||
langs[i++] = lang
|
||||
if(~lang.indexOf('-')) langs[i++] = lang.substr(0, lang.indexOf('-'))
|
||||
if(!lang) return;
|
||||
langs[i++] = lang;
|
||||
if(~lang.indexOf('-')) langs[i++] = lang.substr(0, lang.indexOf('-'));
|
||||
})
|
||||
|
||||
this.build(langs, function(er, translations) {
|
||||
|
|
|
@ -68,43 +68,6 @@ define([
|
|||
time: 6000 // hang on the screen for...
|
||||
});
|
||||
|
||||
function createCookie(name, value, days, path){ /* Warning Internet Explorer doesn't use this it uses the one from pad_utils.js */
|
||||
if (days)
|
||||
{
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
var expires = "; expires=" + date.toGMTString();
|
||||
}
|
||||
else{
|
||||
var expires = "";
|
||||
}
|
||||
|
||||
if(!path){ // If the path isn't set then just whack the cookie on the root path
|
||||
path = "/";
|
||||
}
|
||||
|
||||
//Check if the browser is IE and if so make sure the full path is set in the cookie
|
||||
if((navigator.appName == 'Microsoft Internet Explorer') || ((navigator.appName == 'Netscape') && (new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null))){
|
||||
document.cookie = name + "=" + value + expires + "; path="+document.location;
|
||||
}
|
||||
else{
|
||||
document.cookie = name + "=" + value + expires + "; path=" + path;
|
||||
}
|
||||
}
|
||||
|
||||
function readCookie(name)
|
||||
{
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++)
|
||||
{
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// This array represents all GET-parameters which can be used to change a setting.
|
||||
// name: the parameter-name, eg `?noColors=true` => `noColors`
|
||||
// checkVal: the callback is only executed when
|
||||
|
@ -412,6 +375,7 @@ define([
|
|||
},
|
||||
getIsDebugEnabled: function()
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
return clientVars.debugEnabled;
|
||||
},
|
||||
getPrivilege: function(name)
|
||||
|
@ -445,6 +409,11 @@ define([
|
|||
var newHref = "/p/" + padId;
|
||||
if (options != null)
|
||||
newHref = newHref + '?' + options;
|
||||
=======
|
||||
// start the custom js
|
||||
if (typeof customStart == "function") customStart();
|
||||
handshake();
|
||||
>>>>>>> d31523aa08d123f421248e249e2194f7689f0b06
|
||||
|
||||
if(window.history && window.history.pushState)
|
||||
{
|
||||
|
@ -453,7 +422,33 @@ define([
|
|||
receivedClientVars = false;
|
||||
sendClientReady(false, 'SWITCH_TO_PAD');
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
else // fallback
|
||||
=======
|
||||
});
|
||||
},
|
||||
_afterHandshake: function()
|
||||
{
|
||||
pad.clientTimeOffset = new Date().getTime() - clientVars.serverTimestamp;
|
||||
|
||||
//initialize the chat
|
||||
chat.init(this);
|
||||
getParams();
|
||||
|
||||
padcookie.init(); // initialize the cookies
|
||||
pad.initTime = +(new Date());
|
||||
pad.padOptions = clientVars.initialOptions;
|
||||
|
||||
if ((!browser.msie) && (!(browser.firefox && browser.version.indexOf("1.8.") == 0)))
|
||||
{
|
||||
document.domain = document.domain; // for comet
|
||||
}
|
||||
|
||||
// for IE
|
||||
if (browser.msie)
|
||||
{
|
||||
try
|
||||
>>>>>>> d31523aa08d123f421248e249e2194f7689f0b06
|
||||
{
|
||||
window.location.href = newHref;
|
||||
}
|
||||
|
|
|
@ -144,8 +144,6 @@ define([
|
|||
var v;
|
||||
|
||||
v = getOption('rtlIsTrue', ('rtl' == html10n.getDirection()));
|
||||
// Override from parameters if true
|
||||
if(settings.rtlIsTrue === true) v = true;
|
||||
self.ace.setProperty("rtlIsTrue", v);
|
||||
padutils.setCheckbox($("#options-rtlcheck"), v);
|
||||
|
||||
|
|
|
@ -82,16 +82,18 @@ sauceTestWorker.push({
|
|||
, 'version' : ''
|
||||
});
|
||||
|
||||
/*
|
||||
// IE 8
|
||||
sauceTestWorker.push({
|
||||
'platform' : 'Windows 2003'
|
||||
, 'browserName' : 'iexplore'
|
||||
, 'version' : '8'
|
||||
});
|
||||
*/
|
||||
|
||||
// IE 9
|
||||
sauceTestWorker.push({
|
||||
'platform' : 'Windows 2008'
|
||||
'platform' : 'Windows XP'
|
||||
, 'browserName' : 'iexplore'
|
||||
, 'version' : '9'
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue