diff --git a/bin/checkPad.js b/bin/checkPad.js index 9e0544415..356b07799 100644 --- a/bin/checkPad.js +++ b/bin/checkPad.js @@ -15,7 +15,8 @@ var log4js = require("log4js"); log4js.setGlobalLogLevel("INFO"); var async = require("async"); var db = require('../node/db/DB'); -var Changeset = require('../node/utils/Changeset'); +var CommonCode = require('../node/utils/common_code'); +var Changeset = CommonCode.require("/Changeset"); var padManager; async.series([ diff --git a/bin/convert.js b/bin/convert.js index 4302114c6..c5dc535cd 100644 --- a/bin/convert.js +++ b/bin/convert.js @@ -1,11 +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 = require("../node/utils/Changeset"); -var randomString = require("../node/utils/randomstring"); -var AttributePoolFactory = require("../node/utils/AttributePoolFactory"); +var Changeset = CommonCode.require("/Changeset"); +var randomString = CommonCode.require('/pad_utils').randomString; +var AttributePoolFactory = CommonCode.require("/AttributePoolFactory"); var settingsFile = process.argv[2]; var sqlOutputFile = process.argv[3]; diff --git a/node/db/AuthorManager.js b/node/db/AuthorManager.js index 7c054a56f..9baf63475 100644 --- a/node/db/AuthorManager.js +++ b/node/db/AuthorManager.js @@ -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 = require("../utils/randomstring"); +var randomString = CommonCode.require('/pad_utils').randomString; /** * Checks if the author exists diff --git a/node/db/GroupManager.js b/node/db/GroupManager.js index 7e3b7d6d1..bd294ba62 100644 --- a/node/db/GroupManager.js +++ b/node/db/GroupManager.js @@ -18,9 +18,10 @@ * limitations under the License. */ +var CommonCode = require('../utils/common_code'); var ERR = require("async-stacktrace"); var customError = require("../utils/customError"); -var randomString = require("../utils/randomstring"); +var randomString = CommonCode.require('/pad_utils').randomString; var db = require("./DB").db; var async = require("async"); var padManager = require("./PadManager"); diff --git a/node/db/Pad.js b/node/db/Pad.js index 632eebe8c..99a53143c 100644 --- a/node/db/Pad.js +++ b/node/db/Pad.js @@ -2,9 +2,11 @@ * The pad object, defined with joose */ +var CommonCode = require('../utils/common_code'); var ERR = require("async-stacktrace"); -var Changeset = require("../utils/Changeset"); -var AttributePoolFactory = require("../utils/AttributePoolFactory"); +var Changeset = CommonCode.require("/Changeset"); +var AttributePoolFactory = CommonCode.require("/AttributePoolFactory"); +var randomString = CommonCode.require('/pad_utils').randomString; var db = require("./DB").db; var async = require("async"); var settings = require('../utils/Settings'); @@ -477,15 +479,7 @@ function hash(password, salt) function generateSalt() { - var len = 86; - var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; - var randomstring = ''; - for (var i = 0; i < len; i++) - { - var rnum = Math.floor(Math.random() * chars.length); - randomstring += chars.substring(rnum, rnum + 1); - } - return randomstring; + return randomstring(86); } function compare(hashStr, password) diff --git a/node/db/ReadOnlyManager.js b/node/db/ReadOnlyManager.js index 1e5079c52..e5dab99b4 100644 --- a/node/db/ReadOnlyManager.js +++ b/node/db/ReadOnlyManager.js @@ -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 = require("../utils/randomstring"); +var randomString = CommonCode.require('/pad_utils').randomString; /** * returns a read only id for a pad diff --git a/node/db/SecurityManager.js b/node/db/SecurityManager.js index 4b86d868a..33ab37d44 100644 --- a/node/db/SecurityManager.js +++ b/node/db/SecurityManager.js @@ -18,6 +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"); @@ -25,8 +26,7 @@ var authorManager = require("./AuthorManager"); var padManager = require("./PadManager"); var sessionManager = require("./SessionManager"); var settings = require("../utils/Settings") - -var randomString = require("../utils/randomstring"); +var randomString = CommonCode.require('/pad_utils').randomString; /** * This function controlls the access to a pad, it checks if the user can access a pad. diff --git a/node/db/SessionManager.js b/node/db/SessionManager.js index 084d4a695..c5af33c68 100644 --- a/node/db/SessionManager.js +++ b/node/db/SessionManager.js @@ -18,9 +18,10 @@ * limitations under the License. */ +var CommonCode = require('../utils/common_code'); var ERR = require("async-stacktrace"); var customError = require("../utils/customError"); -var randomString = require("../utils/randomstring"); +var randomString = CommonCode.require('/pad_utils').randomString; var db = require("./DB").db; var async = require("async"); var groupMangager = require("./GroupManager"); diff --git a/node/easysync_tests.js b/node/easysync_tests.js index 5b73b7170..8e7398bea 100644 --- a/node/easysync_tests.js +++ b/node/easysync_tests.js @@ -20,8 +20,9 @@ * limitations under the License. */ -var Changeset = require('./utils/Changeset'); -var AttributePoolFactory = require("./utils/AttributePoolFactory"); +var CommonCode = require('./utils/common_code'); +var Changeset = CommonCode.require("/Changeset"); +var AttributePoolFactory = CommonCode.require("/AttributePoolFactory"); function random() { this.nextInt = function (maxValue) { diff --git a/node/handler/APIHandler.js b/node/handler/APIHandler.js index ca45e1f8f..a7f66151c 100644 --- a/node/handler/APIHandler.js +++ b/node/handler/APIHandler.js @@ -18,11 +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 = require("../utils/randomstring"); +var randomString = CommonCode.require('/pad_utils').randomString; //ensure we have an apikey var apikey = null; diff --git a/node/handler/PadMessageHandler.js b/node/handler/PadMessageHandler.js index 4a078542c..19aa1f9b2 100644 --- a/node/handler/PadMessageHandler.js +++ b/node/handler/PadMessageHandler.js @@ -18,11 +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 = require("../utils/Changeset"); -var AttributePoolFactory = require("../utils/AttributePoolFactory"); +var Changeset = CommonCode.require("/Changeset"); +var AttributePoolFactory = CommonCode.require("/AttributePoolFactory"); var authorManager = require("../db/AuthorManager"); var readOnlyManager = require("../db/ReadOnlyManager"); var settings = require('../utils/Settings'); diff --git a/node/handler/TimesliderMessageHandler.js b/node/handler/TimesliderMessageHandler.js index b30a9fc9d..188068430 100644 --- a/node/handler/TimesliderMessageHandler.js +++ b/node/handler/TimesliderMessageHandler.js @@ -18,11 +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 = require("../utils/Changeset"); -var AttributePoolFactory = require("../utils/AttributePoolFactory"); +var Changeset = CommonCode.require("/Changeset"); +var AttributePoolFactory = CommonCode.require("/AttributePoolFactory"); var settings = require('../utils/Settings'); var authorManager = require("../db/AuthorManager"); var log4js = require('log4js'); diff --git a/node/utils/ExportDokuWiki.js b/node/utils/ExportDokuWiki.js index 48e4b2915..abe6d3471 100644 --- a/node/utils/ExportDokuWiki.js +++ b/node/utils/ExportDokuWiki.js @@ -15,7 +15,8 @@ */ var async = require("async"); -var Changeset = require("./Changeset"); +var CommonCode = require('./common_code'); +var Changeset = CommonCode.require("/Changeset"); var padManager = require("../db/PadManager"); function getPadDokuWiki(pad, revNum, callback) diff --git a/node/utils/ExportHtml.js b/node/utils/ExportHtml.js index d4be80d20..afeafd3a9 100644 --- a/node/utils/ExportHtml.js +++ b/node/utils/ExportHtml.js @@ -14,10 +14,12 @@ * limitations under the License. */ +var CommonCode = require('./common_code'); var async = require("async"); -var Changeset = require("./Changeset"); +var Changeset = CommonCode.require("/Changeset"); var padManager = require("../db/PadManager"); var ERR = require("async-stacktrace"); +var Security = CommonCode.require('/security'); function getPadPlainText(pad, revNum) { @@ -269,7 +271,7 @@ function getHTMLFromAtext(pad, atext) //from but they break the abiword parser and are completly useless s = s.replace(String.fromCharCode(12), ""); - assem.append(_escapeHTML(s)); + assem.append(_encodeWhitespace(Security.escapeHTML(s))); } // end iteration over spans in line var tags2close = []; @@ -292,7 +294,7 @@ function getHTMLFromAtext(pad, atext) var url = urlData[1]; var urlLength = url.length; processNextChars(startIndex - idx); - assem.append(''); + assem.append(''); processNextChars(urlLength); assem.append(''); }); @@ -493,25 +495,7 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback) }); } -function _escapeHTML(s) -{ - var re = /[&"<>]/g; - if (!re.MAP) - { - // persisted across function calls! - re.MAP = { - '&': '&', - '"': '"', - '<': '<', - '>': '>' - }; - } - - s = s.replace(re, function (c) - { - return re.MAP[c]; - }); - +function _encodeWhitespace(s) { return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c) { return "&#" +c.charCodeAt(0) + ";" diff --git a/node/utils/ImportHtml.js b/node/utils/ImportHtml.js index 1b0bcaea7..ce8663697 100644 --- a/node/utils/ImportHtml.js +++ b/node/utils/ImportHtml.js @@ -17,9 +17,10 @@ var jsdom = require('jsdom-nocontextifiy').jsdom; var log4js = require('log4js'); -var Changeset = require("./Changeset"); -var contentcollector = require("./contentcollector"); -var map = require("../../static/js/ace2_common.js").map; +var CommonCode = require('../utils/common_code'); +var Changeset = CommonCode.require("/Changeset"); +var contentcollector = CommonCode.require("/contentcollector"); +var map = CommonCode.require("/ace2_common").map; function setPadHTML(pad, html, callback) { diff --git a/node/utils/common_code.js b/node/utils/common_code.js new file mode 100644 index 000000000..359c9cfec --- /dev/null +++ b/node/utils/common_code.js @@ -0,0 +1,22 @@ +/** + * 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 CLIENT_JS_SRC = __dirname + '/../../static/js/'; +var client_require = RequireKernel.requireForPaths('file://' + CLIENT_JS_SRC); + +exports.require = client_require; diff --git a/node/utils/contentcollector.js b/node/utils/contentcollector.js deleted file mode 100644 index a7fa940a6..000000000 --- a/node/utils/contentcollector.js +++ /dev/null @@ -1,692 +0,0 @@ -// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.contentcollector -// %APPJET%: import("etherpad.collab.ace.easysync2.Changeset"); -// %APPJET%: import("etherpad.admin.plugins"); -/** - * 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 Changeset = require("../utils/Changeset"); - -var _MAX_LIST_LEVEL = 8; - -function sanitizeUnicode(s) -{ - return s.replace(/[\uffff\ufffe\ufeff\ufdd0-\ufdef\ud800-\udfff]/g, '?'); -} - -function makeContentCollector(collectStyles, browser, apool, domInterface, className2Author) -{ - browser = browser || {}; - - var plugins_; - if (typeof(plugins) != 'undefined') - { - plugins_ = plugins; - } - else - { - plugins_ = {callHook: function () {}}; - } - - var dom = domInterface || { - isNodeText: function(n) - { - return (n.nodeType == 3); - }, - nodeTagName: function(n) - { - return n.tagName; - }, - nodeValue: function(n) - { - return n.nodeValue; - }, - nodeNumChildren: function(n) - { - return n.childNodes.length; - }, - nodeChild: function(n, i) - { - return n.childNodes.item(i); - }, - nodeProp: function(n, p) - { - return n[p]; - }, - nodeAttr: function(n, a) - { - return n.getAttribute(a); - }, - optNodeInnerHTML: function(n) - { - return n.innerHTML; - } - }; - - var _blockElems = { - "div": 1, - "p": 1, - "pre": 1, - "li": 1 - }; - - function isBlockElement(n) - { - return !!_blockElems[(dom.nodeTagName(n) || "").toLowerCase()]; - } - - function textify(str) - { - return sanitizeUnicode( - str.replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' ')); - } - - function getAssoc(node, name) - { - return dom.nodeProp(node, "_magicdom_" + name); - } - - var lines = (function() - { - var textArray = []; - var attribsArray = []; - var attribsBuilder = null; - var op = Changeset.newOp('+'); - var self = { - length: function() - { - return textArray.length; - }, - atColumnZero: function() - { - return textArray[textArray.length - 1] === ""; - }, - startNew: function() - { - textArray.push(""); - self.flush(true); - attribsBuilder = Changeset.smartOpAssembler(); - }, - textOfLine: function(i) - { - return textArray[i]; - }, - appendText: function(txt, attrString) - { - textArray[textArray.length - 1] += txt; - //dmesg(txt+" / "+attrString); - op.attribs = attrString; - op.chars = txt.length; - attribsBuilder.append(op); - }, - textLines: function() - { - return textArray.slice(); - }, - attribLines: function() - { - return attribsArray; - }, - // call flush only when you're done - flush: function(withNewline) - { - if (attribsBuilder) - { - attribsArray.push(attribsBuilder.toString()); - attribsBuilder = null; - } - } - }; - self.startNew(); - return self; - }()); - var cc = {}; - - function _ensureColumnZero(state) - { - if (!lines.atColumnZero()) - { - cc.startNewLine(state); - } - } - var selection, startPoint, endPoint; - var selStart = [-1, -1], - selEnd = [-1, -1]; - var blockElems = { - "div": 1, - "p": 1, - "pre": 1 - }; - - function _isEmpty(node, state) - { - // consider clean blank lines pasted in IE to be empty - if (dom.nodeNumChildren(node) == 0) return true; - if (dom.nodeNumChildren(node) == 1 && getAssoc(node, "shouldBeEmpty") && dom.optNodeInnerHTML(node) == " " && !getAssoc(node, "unpasted")) - { - if (state) - { - var child = dom.nodeChild(node, 0); - _reachPoint(child, 0, state); - _reachPoint(child, 1, state); - } - return true; - } - return false; - } - - function _pointHere(charsAfter, state) - { - var ln = lines.length() - 1; - var chr = lines.textOfLine(ln).length; - if (chr == 0 && state.listType && state.listType != 'none') - { - chr += 1; // listMarker - } - chr += charsAfter; - return [ln, chr]; - } - - function _reachBlockPoint(nd, idx, state) - { - if (!dom.isNodeText(nd)) _reachPoint(nd, idx, state); - } - - function _reachPoint(nd, idx, state) - { - if (startPoint && nd == startPoint.node && startPoint.index == idx) - { - selStart = _pointHere(0, state); - } - if (endPoint && nd == endPoint.node && endPoint.index == idx) - { - selEnd = _pointHere(0, state); - } - } - cc.incrementFlag = function(state, flagName) - { - state.flags[flagName] = (state.flags[flagName] || 0) + 1; - } - cc.decrementFlag = function(state, flagName) - { - state.flags[flagName]--; - } - cc.incrementAttrib = function(state, attribName) - { - if (!state.attribs[attribName]) - { - state.attribs[attribName] = 1; - } - else - { - state.attribs[attribName]++; - } - _recalcAttribString(state); - } - cc.decrementAttrib = function(state, attribName) - { - state.attribs[attribName]--; - _recalcAttribString(state); - } - - function _enterList(state, listType) - { - var oldListType = state.listType; - state.listLevel = (state.listLevel || 0) + 1; - if (listType != 'none') - { - state.listNesting = (state.listNesting || 0) + 1; - } - state.listType = listType; - _recalcAttribString(state); - return oldListType; - } - - function _exitList(state, oldListType) - { - state.listLevel--; - if (state.listType != 'none') - { - state.listNesting--; - } - state.listType = oldListType; - _recalcAttribString(state); - } - - function _enterAuthor(state, author) - { - var oldAuthor = state.author; - state.authorLevel = (state.authorLevel || 0) + 1; - state.author = author; - _recalcAttribString(state); - return oldAuthor; - } - - function _exitAuthor(state, oldAuthor) - { - state.authorLevel--; - state.author = oldAuthor; - _recalcAttribString(state); - } - - function _recalcAttribString(state) - { - var lst = []; - for (var a in state.attribs) - { - if (state.attribs[a]) - { - lst.push([a, 'true']); - } - } - if (state.authorLevel > 0) - { - var authorAttrib = ['author', state.author]; - if (apool.putAttrib(authorAttrib, true) >= 0) - { - // require that author already be in pool - // (don't add authors from other documents, etc.) - lst.push(authorAttrib); - } - } - state.attribString = Changeset.makeAttribsString('+', lst, apool); - } - - function _produceListMarker(state) - { - lines.appendText('*', Changeset.makeAttribsString('+', [ - ['list', state.listType], - ['insertorder', 'first'] - ], apool)); - } - cc.startNewLine = function(state) - { - if (state) - { - var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0; - if (atBeginningOfLine && state.listType && state.listType != 'none') - { - _produceListMarker(state); - } - } - lines.startNew(); - } - cc.notifySelection = function(sel) - { - if (sel) - { - selection = sel; - startPoint = selection.startPoint; - endPoint = selection.endPoint; - } - }; - cc.doAttrib = function(state, na) - { - state.localAttribs = (state.localAttribs || []); - state.localAttribs.push(na); - cc.incrementAttrib(state, na); - }; - cc.collectContent = function(node, state) - { - if (!state) - { - state = { - flags: { /*name -> nesting counter*/ - }, - localAttribs: null, - attribs: { /*name -> nesting counter*/ - }, - attribString: '' - }; - } - var localAttribs = state.localAttribs; - state.localAttribs = null; - var isBlock = isBlockElement(node); - var isEmpty = _isEmpty(node, state); - if (isBlock) _ensureColumnZero(state); - var startLine = lines.length() - 1; - _reachBlockPoint(node, 0, state); - if (dom.isNodeText(node)) - { - var txt = dom.nodeValue(node); - var rest = ''; - var x = 0; // offset into original text - if (txt.length == 0) - { - if (startPoint && node == startPoint.node) - { - selStart = _pointHere(0, state); - } - if (endPoint && node == endPoint.node) - { - selEnd = _pointHere(0, state); - } - } - while (txt.length > 0) - { - var consumed = 0; - if (state.flags.preMode) - { - var firstLine = txt.split('\n', 1)[0]; - consumed = firstLine.length + 1; - rest = txt.substring(consumed); - txt = firstLine; - } - else - { /* will only run this loop body once */ - } - if (startPoint && node == startPoint.node && startPoint.index - x <= txt.length) - { - selStart = _pointHere(startPoint.index - x, state); - } - if (endPoint && node == endPoint.node && endPoint.index - x <= txt.length) - { - selEnd = _pointHere(endPoint.index - x, state); - } - var txt2 = txt; - if ((!state.flags.preMode) && /^[\r\n]*$/.exec(txt)) - { - // prevents textnodes containing just "\n" from being significant - // in safari when pasting text, now that we convert them to - // spaces instead of removing them, because in other cases - // removing "\n" from pasted HTML will collapse words together. - txt2 = ""; - } - var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0; - if (atBeginningOfLine) - { - // newlines in the source mustn't become spaces at beginning of line box - txt2 = txt2.replace(/^\n*/, ''); - } - if (atBeginningOfLine && state.listType && state.listType != 'none') - { - _produceListMarker(state); - } - lines.appendText(textify(txt2), state.attribString); - x += consumed; - txt = rest; - if (txt.length > 0) - { - cc.startNewLine(state); - } - } - } - else - { - var tname = (dom.nodeTagName(node) || "").toLowerCase(); - if (tname == "br") - { - cc.startNewLine(state); - } - else if (tname == "script" || tname == "style") - { - // ignore - } - else if (!isEmpty) - { - var styl = dom.nodeAttr(node, "style"); - var cls = dom.nodeProp(node, "className"); - - var isPre = (tname == "pre"); - if ((!isPre) && browser.safari) - { - isPre = (styl && /\bwhite-space:\s*pre\b/i.exec(styl)); - } - if (isPre) cc.incrementFlag(state, 'preMode'); - var oldListTypeOrNull = null; - var oldAuthorOrNull = null; - if (collectStyles) - { - plugins_.callHook('collectContentPre', { - cc: cc, - state: state, - tname: tname, - styl: styl, - cls: cls - }); - if (tname == "b" || (styl && /\bfont-weight:\s*bold\b/i.exec(styl)) || tname == "strong") - { - cc.doAttrib(state, "bold"); - } - if (tname == "i" || (styl && /\bfont-style:\s*italic\b/i.exec(styl)) || tname == "em") - { - cc.doAttrib(state, "italic"); - } - if (tname == "u" || (styl && /\btext-decoration:\s*underline\b/i.exec(styl)) || tname == "ins") - { - cc.doAttrib(state, "underline"); - } - if (tname == "s" || (styl && /\btext-decoration:\s*line-through\b/i.exec(styl)) || tname == "del") - { - cc.doAttrib(state, "strikethrough"); - } - if (tname == "ul" || tname == "ol") - { - var type; - var rr = cls && /(?:^| )list-([a-z]+[12345678])\b/.exec(cls); - type = rr && rr[1] || "bullet" + String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1)); - oldListTypeOrNull = (_enterList(state, type) || 'none'); - } - else if ((tname == "div" || tname == "p") && cls && cls.match(/(?:^| )ace-line\b/)) - { - oldListTypeOrNull = (_enterList(state, type) || 'none'); - } - if (className2Author && cls) - { - var classes = cls.match(/\S+/g); - if (classes && classes.length > 0) - { - for (var i = 0; i < classes.length; i++) - { - var c = classes[i]; - var a = className2Author(c); - if (a) - { - oldAuthorOrNull = (_enterAuthor(state, a) || 'none'); - break; - } - } - } - } - } - - var nc = dom.nodeNumChildren(node); - for (var i = 0; i < nc; i++) - { - var c = dom.nodeChild(node, i); - cc.collectContent(c, state); - } - - if (collectStyles) - { - plugins_.callHook('collectContentPost', { - cc: cc, - state: state, - tname: tname, - styl: styl, - cls: cls - }); - } - - if (isPre) cc.decrementFlag(state, 'preMode'); - if (state.localAttribs) - { - for (var i = 0; i < state.localAttribs.length; i++) - { - cc.decrementAttrib(state, state.localAttribs[i]); - } - } - if (oldListTypeOrNull) - { - _exitList(state, oldListTypeOrNull); - } - if (oldAuthorOrNull) - { - _exitAuthor(state, oldAuthorOrNull); - } - } - } - if (!browser.msie) - { - _reachBlockPoint(node, 1, state); - } - if (isBlock) - { - if (lines.length() - 1 == startLine) - { - cc.startNewLine(state); - } - else - { - _ensureColumnZero(state); - } - } - - if (browser.msie) - { - // in IE, a point immediately after a DIV appears on the next line - _reachBlockPoint(node, 1, state); - } - - state.localAttribs = localAttribs; - }; - // can pass a falsy value for end of doc - cc.notifyNextNode = function(node) - { - // an "empty block" won't end a line; this addresses an issue in IE with - // typing into a blank line at the end of the document. typed text - // goes into the body, and the empty line div still looks clean. - // it is incorporated as dirty by the rule that a dirty region has - // to end a line. - if ((!node) || (isBlockElement(node) && !_isEmpty(node))) - { - _ensureColumnZero(null); - } - }; - // each returns [line, char] or [-1,-1] - var getSelectionStart = function() - { - return selStart; - }; - var getSelectionEnd = function() - { - return selEnd; - }; - - // returns array of strings for lines found, last entry will be "" if - // last line is complete (i.e. if a following span should be on a new line). - // can be called at any point - cc.getLines = function() - { - return lines.textLines(); - }; - - cc.finish = function() - { - lines.flush(); - var lineAttribs = lines.attribLines(); - var lineStrings = cc.getLines(); - - lineStrings.length--; - lineAttribs.length--; - - var ss = getSelectionStart(); - var se = getSelectionEnd(); - - function fixLongLines() - { - // design mode does not deal with with really long lines! - var lineLimit = 2000; // chars - var buffer = 10; // chars allowed over before wrapping - var linesWrapped = 0; - var numLinesAfter = 0; - for (var i = lineStrings.length - 1; i >= 0; i--) - { - var oldString = lineStrings[i]; - var oldAttribString = lineAttribs[i]; - if (oldString.length > lineLimit + buffer) - { - var newStrings = []; - var newAttribStrings = []; - while (oldString.length > lineLimit) - { - //var semiloc = oldString.lastIndexOf(';', lineLimit-1); - //var lengthToTake = (semiloc >= 0 ? (semiloc+1) : lineLimit); - lengthToTake = lineLimit; - newStrings.push(oldString.substring(0, lengthToTake)); - oldString = oldString.substring(lengthToTake); - newAttribStrings.push(Changeset.subattribution(oldAttribString, 0, lengthToTake)); - oldAttribString = Changeset.subattribution(oldAttribString, lengthToTake); - } - if (oldString.length > 0) - { - newStrings.push(oldString); - newAttribStrings.push(oldAttribString); - } - - function fixLineNumber(lineChar) - { - if (lineChar[0] < 0) return; - var n = lineChar[0]; - var c = lineChar[1]; - if (n > i) - { - n += (newStrings.length - 1); - } - else if (n == i) - { - var a = 0; - while (c > newStrings[a].length) - { - c -= newStrings[a].length; - a++; - } - n += a; - } - lineChar[0] = n; - lineChar[1] = c; - } - fixLineNumber(ss); - fixLineNumber(se); - linesWrapped++; - numLinesAfter += newStrings.length; - - newStrings.unshift(i, 1); - lineStrings.splice.apply(lineStrings, newStrings); - newAttribStrings.unshift(i, 1); - lineAttribs.splice.apply(lineAttribs, newAttribStrings); - } - } - return { - linesWrapped: linesWrapped, - numLinesAfter: numLinesAfter - }; - } - var wrapData = fixLongLines(); - - return { - selStart: ss, - selEnd: se, - linesWrapped: wrapData.linesWrapped, - numLinesAfter: wrapData.numLinesAfter, - lines: lineStrings, - lineAttribs: lineAttribs - }; - } - - return cc; -} - -exports.makeContentCollector = makeContentCollector; diff --git a/node/utils/randomstring.js b/node/utils/randomstring.js deleted file mode 100644 index 4c1bba244..000000000 --- a/node/utils/randomstring.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Generates a random String with the given length. Is needed to generate the Author, Group, readonly, session Ids - */ -var randomString = function randomString(len) -{ - var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - var randomstring = ''; - for (var i = 0; i < len; i++) - { - var rnum = Math.floor(Math.random() * chars.length); - randomstring += chars.substring(rnum, rnum + 1); - } - return randomstring; -}; - -module.exports = randomString; diff --git a/node/utils/tar.json b/node/utils/tar.json index b319791cf..e922dddeb 100644 --- a/node/utils/tar.json +++ b/node/utils/tar.json @@ -1,6 +1,7 @@ { "pad.js": [ "jquery.js" + , "security.js" , "pad.js" , "ace2_common.js" , "pad_utils.js" @@ -25,6 +26,7 @@ ] , "timeslider.js": [ "jquery.js" + , "security.js" , "plugins.js" , "undo-xpopup.js" , "json2.js" @@ -39,10 +41,11 @@ , "pad_modals.js" , "pad_savedrevs.js" , "pad_impexp.js" - , "easysync2_client.js" - , "domline_client.js" - , "linestylefilter_client.js" - , "cssmanager_client.js" + , "AttributePoolFactory.js" + , "Changeset.js" + , "domline.js" + , "linestylefilter.js" + , "cssmanager.js" , "broadcast.js" , "broadcast_slider.js" , "broadcast_revisions.js" @@ -50,9 +53,11 @@ ] , "ace2_inner.js": [ "ace2_common.js" + , "AttributePoolFactory.js" + , "Changeset.js" + , "security.js" , "skiplist.js" , "virtual_lines.js" - , "easysync2.js" , "cssmanager.js" , "colorutils.js" , "undomodule.js" diff --git a/node/utils/AttributePoolFactory.js b/static/js/AttributePoolFactory.js similarity index 97% rename from node/utils/AttributePoolFactory.js rename to static/js/AttributePoolFactory.js index 807c2b393..00b58dbb3 100644 --- a/node/utils/AttributePoolFactory.js +++ b/static/js/AttributePoolFactory.js @@ -1,8 +1,8 @@ /** - * This code represents the Attribute Pool Object of the original Etherpad. + * This code represents the Attribute Pool Object of the original Etherpad. * 90% of the code is still like in the original Etherpad * Look at https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js - * You can find a explanation what a attribute pool is here: + * You can find a explanation what a attribute pool is here: * https://github.com/Pita/etherpad-lite/blob/master/doc/easysync/easysync-notes.txt */ diff --git a/node/utils/Changeset.js b/static/js/Changeset.js similarity index 99% rename from node/utils/Changeset.js rename to static/js/Changeset.js index 9e1b60ebe..715836d5f 100644 --- a/node/utils/Changeset.js +++ b/static/js/Changeset.js @@ -1,10 +1,10 @@ /* * This is the Changeset library copied from the old Etherpad with some modifications to use it in node.js * Can be found in https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js - */ + */ /** - * This code is mostly from the old Etherpad. Please help us to comment this code. + * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED */ @@ -25,7 +25,7 @@ * limitations under the License. */ -var AttributePoolFactory = require("./AttributePoolFactory"); +var AttributePoolFactory = require("/AttributePoolFactory"); var _opt = null; diff --git a/static/js/ace2_common.js b/static/js/ace2_common.js index 1ce7810aa..b4c72a92f 100644 --- a/static/js/ace2_common.js +++ b/static/js/ace2_common.js @@ -20,6 +20,7 @@ * limitations under the License. */ +var Security = require('/security'); function isNodeText(node) { @@ -137,14 +138,7 @@ function binarySearchInfinite(expectedLength, func) function htmlPrettyEscape(str) { - return str.replace(/[&"<>]/g, function (c) { - return { - '&': '&', - '"': '"', - '<': '<', - '>': '>' - }[c] || c; - }).replace(/\r?\n/g, '\\n'); + return Security.escapeHTML(str).replace(/\r?\n/g, '\\n'); } exports.isNodeText = isNodeText; diff --git a/static/js/ace2_inner.js b/static/js/ace2_inner.js index 31d4dac94..d21135743 100644 --- a/static/js/ace2_inner.js +++ b/static/js/ace2_inner.js @@ -42,8 +42,8 @@ var colorutils = require('/colorutils').colorutils; var makeContentCollector = require('/contentcollector').makeContentCollector; var makeCSSManager = require('/cssmanager').makeCSSManager; var domline = require('/domline').domline; -var AttribPool = require('/easysync2').AttribPool; -var Changeset = require('/easysync2').Changeset; +var AttribPool = require('/AttributePoolFactory').createAttributePool; +var Changeset = require('/Changeset'); var linestylefilter = require('/linestylefilter').linestylefilter; var newSkipList = require('/skiplist').newSkipList; var undoModule = require('/undomodule').undoModule; diff --git a/static/js/broadcast.js b/static/js/broadcast.js index 020f47e7c..4a7b01681 100644 --- a/static/js/broadcast.js +++ b/static/js/broadcast.js @@ -20,11 +20,11 @@ * limitations under the License. */ -var makeCSSManager = require('/cssmanager_client').makeCSSManager; -var domline = require('/domline_client').domline; -var Changeset = require('/easysync2_client').Changeset; -var AttribPool = require('/easysync2_client').AttribPool; -var linestylefilter = require('/linestylefilter_client').linestylefilter; +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; // These parameters were global, now they are injected. A reference to the diff --git a/static/js/changesettracker.js b/static/js/changesettracker.js index 7b0fb3e46..e34dc107e 100644 --- a/static/js/changesettracker.js +++ b/static/js/changesettracker.js @@ -20,8 +20,8 @@ * limitations under the License. */ -var Changeset = require('/easysync2').Changeset; -var AttribPool = require('/easysync2').AttribPool; +var AttribPool = require('/AttributePoolFactory').createAttributePool; +var Changeset = require('/Changeset'); function makeChangesetTracker(scheduler, apool, aceCallbacksProvider) { diff --git a/static/js/contentcollector.js b/static/js/contentcollector.js index 0437ccd7b..96dc4b7dd 100644 --- a/static/js/contentcollector.js +++ b/static/js/contentcollector.js @@ -25,7 +25,7 @@ var _MAX_LIST_LEVEL = 8; -var Changeset = require('/easysync2').Changeset +var Changeset = require('/Changeset'); var plugins = require('/plugins').plugins; function sanitizeUnicode(s) diff --git a/static/js/cssmanager_client.js b/static/js/cssmanager_client.js deleted file mode 100644 index 6d9d989e8..000000000 --- a/static/js/cssmanager_client.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - * This code is mostly from the old Etherpad. Please help us to comment this code. - * This helps other people to understand this code better and helps them to improve it. - * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED - */ - -// DO NOT EDIT THIS FILE, edit infrastructure/ace/www/cssmanager.js -/** - * Copyright 2009 Google Inc. - * - * 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. - */ - -function makeCSSManager(emptyStylesheetTitle) -{ - - function getSheetByTitle(title) - { - var allSheets = document.styleSheets; - for (var i = 0; i < allSheets.length; i++) - { - var s = allSheets[i]; - if (s.title == title) - { - return s; - } - } - return null; - } - -/*function getSheetTagByTitle(title) { - var allStyleTags = document.getElementsByTagName("style"); - for(var i=0;i= 0) - { - browserDeleteRule(i); - selectorList.splice(i, 1); - } - } - - return { - selectorStyle: selectorStyle, - removeSelectorStyle: removeSelectorStyle, - info: function() - { - return selectorList.length + ":" + browserRules().length; - } - }; -} - -exports.makeCSSManager = makeCSSManager; diff --git a/static/js/domline.js b/static/js/domline.js index 8d8c2ea9e..15528bf7a 100644 --- a/static/js/domline.js +++ b/static/js/domline.js @@ -26,6 +26,7 @@ // requires: plugins // requires: undefined +var Security = require('/security'); var plugins = require('/plugins').plugins; var map = require('/ace2_common').map; @@ -103,17 +104,17 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument) if (listType) { listType = listType[1]; - start = start?'start="'+start[1]+'"':''; + start = start?'start="'+Security.escapeHTMLAttribute(start[1])+'"':''; if (listType) { if(listType.indexOf("number") < 0) { - preHtml = '