diff --git a/CHANGELOG.md b/CHANGELOG.md index 74d06f45..df249c25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +# 1.6.5 + * SECURITY: Escape data when listing available plugins + * FIX: Fix typo in apicalls.js which prevented importing isValidJSONPName + * FIX: fixed plugin dependency issue + * FIX: Update iframe_editor.css + * FIX: unbreak Safari iOS line wrapping + +# 1.6.4 + * SECURITY: exploitable /admin access - CVE-2018-9845 + * SECURITY: DoS with pad exports - CVE-2018-9327 + * SECURITY: Remote Code Execution - CVE-2018-9326 + * SECURITY: Pad data leak - CVE-2018-9325 + * Fix: Admin redirect URL + * Fix: Various script Fixes + * Fix: Various CSS/Style/Layout fixes + * NEW: Improved Pad contents readability + * NEW: Hook: onAccessCheck + * NEW: SESSIONKEY and APIKey customizable path + * NEW: checkPads script + * NEW: Support "cluster mode" + # 1.6.3 * SECURITY: Update ejs * SECURITY: xss vulnerability when reading window.location.href @@ -56,7 +77,7 @@ * NEW: Allow LibreOffice to be used when exporting a pad * NEW: Create hook exportHtmlAdditionalTagsWithData * NEW: Improve DB migration performance - * NEW: allow settings to be applied from the filesystem + * NEW: allow settings to be applied from the filesystem * NEW: remove applySettings hook and allow credentials.json to be part of core * NEW: Use exec to switch to node process * NEW: Validate incoming color codes @@ -85,7 +106,7 @@ * Fix: switchToPad method * Fix: Dead keys * Fix: Preserve new lines in copy-pasted text - * Fix: Compatibility mode on IE + * Fix: Compatibility mode on IE * Fix: Content Collector to get the class of the DOM-node * Fix: Timeslider export links * Fix: Double prompt on file upload @@ -212,7 +233,7 @@ * Fix: Session Deletion error * Fix: Allow browser tabs to be cycled when focus is in editor * Fix: Various Editor issues with Easysync potentially entering forever loop on bad changeset - + # 1.4 * NEW: Disable toolbar items through settings.json * NEW: Internal stats/metrics engine @@ -244,7 +265,7 @@ # 1.3 * NEW: We now follow the semantic versioning scheme! * NEW: Option to disable IP logging - * NEW: Localisation updates from http://translatewiki.net. + * NEW: Localisation updates from http://translatewiki.net. * Fix: Fix readOnly group pads * Fix: don't fetch padList on every request @@ -337,7 +358,7 @@ * NEW: Add authorId to chat and userlist as a data attribute * NEW: Refactor and fix our frontend tests * NEW: Localisation updates - + # 1.2.81 * Fix: CtrlZ-Y for Undo Redo @@ -377,7 +398,7 @@ * Other: Change loading message asking user to please wait on first build * Other: Allow etherpad to use global npm installation (Safe since node 6.3) * Other: Better documentation for log rotation and log message handling - + # 1.2.7 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 09ddc286..66946080 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Developer Guidelines +# Contributor Guidelines (Please talk to people on the mailing list before you change this page, see our section on [how to get in touch](https://github.com/ether/etherpad-lite#get-in-touch)) ## How to write a bug report @@ -35,7 +35,7 @@ The logfile location is defined in startup script or the log is directly shown i To make sure everybody is going in the same direction: * easy to install for admins and easy to use for people * easy to integrate into other apps, but also usable as standalone -* using less resources on server side +* lightweight and scalable * extensible, as much functionality should be extendable with plugins so changes don't have to be done in core. Also, keep it maintainable. We don't wanna end up as the monster Etherpad was! @@ -92,3 +92,19 @@ You can build the docs e.g. produce html, using `make docs`. At some point in th ## Testing Front-end tests are found in the `tests/frontend/` folder in the repository. Run them by pointing your browser to `/tests/frontend`. + +## Things you can help with +Etherpad is much more than software. So if you aren't a developer then worry not, there is still a LOT you can do! A big part of what we do is community engagement. You can help in the following ways + * Triage bugs (applying labels) and confirming their existance + * Testing fixes (simply applying them and seeing if it fixes your issue or not) - Some git experience required + * Notifying large site admins of new releases + * Writing Changelogs for releases + * Creating Windows packages + * Creating releases + * Bumping dependencies periodically and checking they don't break anything + * Write proposals for grants + * Co-Author and Publish CVEs + * Work with SFC to maintain legal side of project + * Maintain TODO page - https://github.com/ether/etherpad-lite/wiki/TODO#IMPORTANT_TODOS + * Replying to messages on IRC / The Mailing list / Emails + diff --git a/README.md b/README.md index 3ab7e358..d8d7b621 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Etherpad is a really-real time collaborative editor scalable to thousands of sim ``` curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash - sudo apt-get install -y nodejs -git clone git://github.com/ether/etherpad-lite.git && cd etherpad-lite && bin/run.sh +git clone https://github.com/ether/etherpad-lite.git && cd etherpad-lite && bin/run.sh ``` ## GNU/Linux and other UNIX-like systems diff --git a/src/locales/pms.json b/src/locales/pms.json index 80a857e3..cdc80bea 100644 --- a/src/locales/pms.json +++ b/src/locales/pms.json @@ -44,5 +44,86 @@ "pad.importExport.import": "Carié n'archivi o document ëd test", "pad.importExport.importSuccessful": "Bele fàit!", "pad.importExport.export": "Esporté ël feuj atual coma:", - "pad.importExport.exportetherpad": "Etherpad" + "pad.importExport.exportetherpad": "Etherpad", + "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportplain": "Mach test", + "pad.importExport.exportword": "Microsoft Word", + "pad.importExport.exportpdf": "PDF", + "pad.importExport.exportopen": "ODF (Open Document Format)", + "pad.importExport.abiword.innerHTML": "A peul mach amporté dij formà ëd test sempi o HTML. Për dle fonsionalità d'amportassion pi avansà, ch'a anstala AbiWord.", + "pad.modals.connected": "Colegà.", + "pad.modals.reconnecting": "Neuva conession a sò feuj...", + "pad.modals.forcereconnect": "Forsé la neuva conession", + "pad.modals.reconnecttimer": "Tentativ ëd neuva conession", + "pad.modals.cancel": "Anulé", + "pad.modals.userdup": "Duvertà an n'àutra fnestra", + "pad.modals.userdup.explanation": "Ës feuj a smija esse duvert an vàire fnestre ansima a st'ordinator.", + "pad.modals.userdup.advice": "Coleghesse torna për dovré costa fnestra.", + "pad.modals.unauth": "Nen autorisà", + "pad.modals.unauth.explanation": "Ij sò përmess a son cangià antramentre ch'a vëdìa costa pàgina. Ch'a sërca ëd coleghesse torna.", + "pad.modals.looping.explanation": "A-i é dij problema ëd comunicassion con ël servent ëd sincronisassion.", + "pad.modals.looping.cause": "Peul desse che chiel a l'é colegasse con un para-feu o un mandatari incompatìbil.", + "pad.modals.initsocketfail": "Ël servent a l'é introvàbil.", + "pad.modals.initsocketfail.explanation": "Impossìbil coleghesse al servent ëd sincronisassion.", + "pad.modals.initsocketfail.cause": "A l'é probàbil che sòn a sia dovù a sò navigador o a soa conession an sl'aragnà.", + "pad.modals.slowcommit.explanation": "Ël servent a rëspond nen.", + "pad.modals.slowcommit.cause": "Sòn a podrìa esse dovù a dij problema ëd conession a l'aragnà.", + "pad.modals.badChangeset.explanation": "Na modìfica ch'a l'ha fàit a l'é stàita cassificà tanme ilegal dal servent ëd sincronisassion.", + "pad.modals.badChangeset.cause": "Sòn a podrìa esse dovù a na bruta configurassion dël servent o a chèich àutr comportament nen ëspetà. Për piasì, ch'a contata l'aministrator dël servissi, s'a pensa ch'a sia n'eror. Ch'a preuva a rintré torna ant ël sistema për andé anans a modifiché.", + "pad.modals.corruptPad.explanation": "Ël feuj al qual a sërca d'acede a l'é corompù.", + "pad.modals.corruptPad.cause": "Sòn a podrìa esse dovù a na configurassion ësbalià dël servent o a chèich àutr comportament nen ëspetà. Për piasì, ch'a contata l'aministrator dël servissi.", + "pad.modals.deleted": "Dëscancelà.", + "pad.modals.deleted.explanation": "Ës feuj a l'é stàit eliminà.", + "pad.modals.disconnected": "A l'é stàit dëscolegà", + "pad.modals.disconnected.explanation": "La conession al servent a l'é perdusse", + "pad.modals.disconnected.cause": "Ël servent a podrìa esse indisponìbil. Për piasì, ch'a anforma l'aministrator dël servissi si ël problema a persist.", + "pad.share": "Partagé 's feuj", + "pad.share.readonly": "Mach letura", + "pad.share.link": "Liura", + "pad.share.emebdcode": "Ancorporé na liura", + "pad.chat": "Ciaciarada", + "pad.chat.title": "Duverté la ciaciarada për cost feuj.", + "pad.chat.loadmessages": "Carié pi 'd mëssagi", + "timeslider.pageTitle": "Stòria dinàmica ëd {{appTitle}}", + "timeslider.toolbar.returnbutton": "Torné al feuj", + "timeslider.toolbar.authors": "Autor:", + "timeslider.toolbar.authorsList": "Gnun autor", + "timeslider.toolbar.exportlink.title": "Esporté", + "timeslider.exportCurrent": "Esporté la version corenta tanme:", + "timeslider.version": "Version {{version}}", + "timeslider.saved": "Argistrà ai {{day}} {{month}} {{year}}", + "timeslider.playPause": "Letura / Pàusa dij contnù dël feuj", + "timeslider.backRevision": "Andé andaré ëd na revision ant ës feuj", + "timeslider.forwardRevision": "Andé anans ëd na revision ant ëd feuj", + "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", + "timeslider.month.january": "Gené", + "timeslider.month.february": "Fërvé", + "timeslider.month.march": "Mars", + "timeslider.month.april": "Avril", + "timeslider.month.may": "Maj", + "timeslider.month.june": "Giugn", + "timeslider.month.july": "Luj", + "timeslider.month.august": "Ost", + "timeslider.month.september": "Stèmber", + "timeslider.month.october": "Otóber", + "timeslider.month.november": "Novèmber", + "timeslider.month.december": "Dzèmber", + "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor anònim, other: autor anònim ]}", + "pad.savedrevs.marked": "Sa revision a l'é adess marcà tanme revision argistrà", + "pad.savedrevs.timeslider": "A peul vëdde le revision argistrà an visitand la stòria", + "pad.userlist.entername": "Ch'a buta sò nòm", + "pad.userlist.unnamed": "anònim", + "pad.userlist.guest": "Anvità", + "pad.userlist.deny": "Arfudé", + "pad.userlist.approve": "Aprové", + "pad.editbar.clearcolors": "Dëscancelé ij color ëd paternità dj'autor an tut ël document?", + "pad.impexp.importbutton": "Amporté adess", + "pad.impexp.importing": "An camin ch'as ampòrta...", + "pad.impexp.confirmimport": "Amportand n'archivi as dëscancelërà ël test corent dël feuj. É-lo sigur ëd vorèj felo?", + "pad.impexp.convertFailed": "I l'oma nen podù amporté s'archivi. Për piasì, ch'a deuvra n'àutr formà ëd document o ch'a còpia e ancòla a man", + "pad.impexp.padHasData": "I l'oma nen podù amporté s'archivi përché 's feuj a l'ha già avù dle modìfiche; për piasì, ch'a ampòrta un feuj neuv", + "pad.impexp.uploadFailed": "Ël cariament a l'ha falì, për piasì ch'a preuva torna", + "pad.impexp.importfailed": "Amportassion falìa", + "pad.impexp.copypaste": "Për piasì, ch'a còpia e ancòla", + "pad.impexp.exportdisabled": "L'esportassion an formà {{type}} a l'é disativà. Për piasì, ch'a contata sò aministrator ëd sistema për ij detaj." } diff --git a/src/locales/zh-hant.json b/src/locales/zh-hant.json index 17591884..2a7d6d1e 100644 --- a/src/locales/zh-hant.json +++ b/src/locales/zh-hant.json @@ -117,7 +117,7 @@ "timeslider.month.october": "10月", "timeslider.month.november": "11月", "timeslider.month.december": "12月", - "timeslider.unnamedauthors": "{{num}}匿名{[plural(num) 作者]}", + "timeslider.unnamedauthors": "{{num}} 個匿名{[plural(num) one:作者, other:作者]}", "pad.savedrevs.marked": "標記此修訂版本為已儲存修訂版本。", "pad.savedrevs.timeslider": "您可使用時段滑標來查看先前保存的版本內容", "pad.userlist.entername": "輸入您的姓名", diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index 060bca7b..b575125a 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -1153,6 +1153,101 @@ function handleClientReady(client, message) client.join(padIds.padId); //Save the revision in sessioninfos, we take the revision from the info the client send to us sessioninfos[client.id].rev = message.client_rev; + + //During the client reconnect, client might miss some revisions from other clients. By using client revision, + //this below code sends all the revisions missed during the client reconnect + var revisionsNeeded = []; + var changesets = {}; + + var startNum = message.client_rev + 1; + var endNum = pad.getHeadRevisionNumber() + 1; + + async.series([ + //push all the revision numbers needed into revisionsNeeded array + function(callback) + { + var headNum = pad.getHeadRevisionNumber(); + if (endNum > headNum+1) + endNum = headNum+1; + if (startNum < 0) + startNum = 0; + + for(var r=startNum;r= lists.length)//means we are on a deeper level of indentation than the previous line { if(lists.length > 0){ @@ -381,14 +373,14 @@ function getHTMLFromAtext(pad, atext, authorColors) if(toOpen > 0){ pieces.push(new Array(toOpen + 1).join('
    ')) } - pieces.push('
    1. ', context.lineContent || '
      '); + pieces.push('
      1. ', lineContent || '
        '); } else { if(toOpen > 0){ pieces.push(new Array(toOpen + 1).join('
          ')) } - pieces.push('
          • ', context.lineContent || '
            '); + pieces.push('
            • ', lineContent || '
              '); } } //the following code *seems* dead after my patch. @@ -424,16 +416,16 @@ function getHTMLFromAtext(pad, atext, authorColors) if(lists[lists.length - 1][1] == "number") { pieces.push(new Array(toClose+1).join('
      ')) - pieces.push('
    2. ', context.lineContent || '
      '); + pieces.push('
    3. ', lineContent || '
      '); } else { pieces.push(new Array(toClose+1).join('')) - pieces.push('
    4. ', context.lineContent || '
      '); + pieces.push('
    5. ', lineContent || '
      '); } lists = lists.slice(0,whichList+1) } else { - pieces.push('
    6. ', context.lineContent || '
      '); + pieces.push('
    7. ', lineContent || '
      '); } } } @@ -459,9 +451,16 @@ function getHTMLFromAtext(pad, atext, authorColors) padId: pad.id } - hooks.callAll("getLineHTMLForExport", context); + var lineContentFromHook = hooks.callAllStr("getLineHTMLForExport", context, " ", " ", ""); - pieces.push(context.lineContent, '
      '); + if (lineContentFromHook) + { + pieces.push(lineContentFromHook, ''); + } + else + { + pieces.push(lineContent, '
      '); + } } } diff --git a/src/package.json b/src/package.json index 67ac8a0e..9813d6ab 100644 --- a/src/package.json +++ b/src/package.json @@ -17,14 +17,14 @@ "etherpad-require-kernel" : "1.0.9", "resolve" : "1.1.7", "socket.io" : "1.7.3", - "ueberdb2" : "0.3.7", + "ueberdb2" : "0.3.8", "express" : "4.13.4", "express-session" : "1.13.0", "cookie-parser" : "1.3.4", "async" : "0.9.0", "clean-css" : "3.4.19", "uglify-js" : "2.6.2", - "formidable" : "1.0.17", + "formidable" : "1.2.1", "log4js" : "0.6.35", "cheerio" : "0.20.0", "async-stacktrace" : "0.0.2", @@ -42,13 +42,12 @@ "channels" : "0.0.4", "jsonminify" : "0.4.1", "measured" : "1.1.0", - "mocha" : "2.4.5", - "supertest" : "1.2.0", - "is-var-name" : "1.0.0" - }, + "mocha" : "5.0.5", + "supertest" : "3.0.0" + }, "bin": { "etherpad-lite": "./node/server.js" }, "devDependencies": { - "wd" : "0.3.11" + "wd" : "1.6.1" }, "engines" : { "node" : ">=0.10.0", "npm" : ">=1.0" @@ -56,6 +55,6 @@ "repository" : { "type" : "git", "url" : "http://github.com/ether/etherpad-lite.git" }, - "version" : "1.6.3", + "version" : "1.6.5", "license" : "Apache-2.0" } diff --git a/src/static/css/iframe_editor.css b/src/static/css/iframe_editor.css index 757bfa96..9aa003aa 100644 --- a/src/static/css/iframe_editor.css +++ b/src/static/css/iframe_editor.css @@ -31,17 +31,13 @@ body { body.grayedout { background-color: #eee !important } #innerdocbody { - font-size: 16px; /* overridden by body.style */ + font-size: 12px; /* overridden by body.style */ font-family:Arial, sans-serif; /* overridden by body.style */ line-height: 16px; /* overridden by body.style */ background-color: white; color: black; } -.innerdocbody>div{ - padding: 1px; -} - body.doesWrap { /* white-space: pre-wrap; */ @@ -62,11 +58,9 @@ body.doesWrap { white-space: normal; } -@-moz-document url-prefix() { - body.doesWrap:not(.noprewrap) > div{ - /* Related to #1766 */ - white-space: pre-wrap; - } +body.doesWrap:not(.noprewrap) > div{ + /* Related to #1766 */ + white-space: pre-wrap; } #innerdocbody { diff --git a/src/static/css/pad.css b/src/static/css/pad.css index eb62a6f9..484e6f2a 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -1072,9 +1072,9 @@ input[type=checkbox] { overflow: auto; } #mycolorpicker { - left: -73px; - top:auto !important; - bottom:33px !important; + left: 0px; + top:37px !important; + position:fixed; /* #mycolorpicker: width -#users: width */; } #editorcontainer { diff --git a/src/static/js/admin/plugins.js b/src/static/js/admin/plugins.js index 3f88d9b1..c9a24487 100644 --- a/src/static/js/admin/plugins.js +++ b/src/static/js/admin/plugins.js @@ -79,12 +79,17 @@ $(document).ready(function () { for (attr in plugin) { if(attr == "name"){ // Hack to rewrite URLS into name - row.find(".name").html(""+plugin['name'].substr(3)+""); // remove 'ep_' - }else{ + var link = $(''); + link.attr('href', 'https://npmjs.org/package/'+plugin['name']); + link.attr('plugin', 'Plugin details'); + link.attr('target', '_blank'); + link.text(plugin['name'].substr(3)); + row.find('.name').append(link); + } else { row.find("." + attr).text(plugin[attr]); } } - row.find(".version").html( plugin.version ); + row.find(".version").text(plugin.version); row.addClass(plugin.name) row.data('plugin', plugin.name) container.append(row); diff --git a/src/static/js/collab_client.js b/src/static/js/collab_client.js index fd0d9d44..4bcc6ad2 100644 --- a/src/static/js/collab_client.js +++ b/src/static/js/collab_client.js @@ -60,6 +60,8 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) var debugMessages = []; var msgQueue = []; + var isPendingRevision = false; + tellAceAboutHistoricalAuthors(serverVars.historicalAuthorData); tellAceActiveAuthorInfo(initialUserInfo); @@ -178,23 +180,36 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) editor.applyChangesToBase(changeset, author, apool); } } + if (isPendingRevision) { + setIsPendingRevision(false); + } } var sentMessage = false; - var userChangesData = editor.prepareUserChangeset(); - if (userChangesData.changeset) + // Check if there are any pending revisions to be received from server. + // Allow only if there are no pending revisions to be received from server + if (!isPendingRevision) { - lastCommitTime = t; - state = "COMMITTING"; - stateMessage = { - type: "USER_CHANGES", - baseRev: rev, - changeset: userChangesData.changeset, - apool: userChangesData.apool - }; - sendMessage(stateMessage); - sentMessage = true; - callbacks.onInternalAction("commitPerformed"); + var userChangesData = editor.prepareUserChangeset(); + if (userChangesData.changeset) + { + lastCommitTime = t; + state = "COMMITTING"; + stateMessage = { + type: "USER_CHANGES", + baseRev: rev, + changeset: userChangesData.changeset, + apool: userChangesData.apool + }; + sendMessage(stateMessage); + sentMessage = true; + callbacks.onInternalAction("commitPerformed"); + } + } + else + { + // run again in a few seconds, to check if there was a reconnection attempt + setTimeout(wrapRecordingErrors("setTimeout(handleUserChanges)", handleUserChanges), 3000); } if (sentMessage) @@ -330,6 +345,69 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) }); handleUserChanges(); } + else if (msg.type == 'CLIENT_RECONNECT') + { + // Server sends a CLIENT_RECONNECT message when there is a client reconnect. Server also returns + // all pending revisions along with this CLIENT_RECONNECT message + if (msg.noChanges) + { + // If no revisions are pending, just make everything normal + setIsPendingRevision(false); + return; + } + + var headRev = msg.headRev; + var newRev = msg.newRev; + var changeset = msg.changeset; + var author = (msg.author || ''); + var apool = msg.apool; + + if (msgQueue.length > 0) + { + if (newRev != (msgQueue[msgQueue.length - 1].newRev + 1)) + { + window.console.warn("bad message revision on CLIENT_RECONNECT: " + newRev + " not " + (msgQueue[msgQueue.length - 1][0] + 1)); + // setChannelState("DISCONNECTED", "badmessage_acceptcommit"); + return; + } + msg.type = "NEW_CHANGES"; + msgQueue.push(msg); + return; + } + + if (newRev != (rev + 1)) + { + window.console.warn("bad message revision on CLIENT_RECONNECT: " + newRev + " not " + (rev + 1)); + // setChannelState("DISCONNECTED", "badmessage_acceptcommit"); + return; + } + + rev = newRev; + if (author == pad.getUserId()) + { + editor.applyPreparedChangesetToBase(); + setStateIdle(); + callCatchingErrors("onInternalAction", function() + { + callbacks.onInternalAction("commitAcceptedByServer"); + }); + callCatchingErrors("onConnectionTrouble", function() + { + callbacks.onConnectionTrouble("OK"); + }); + handleUserChanges(); + } + else + { + editor.applyChangesToBase(changeset, author, apool); + } + + if (newRev == headRev) + { + // Once we have applied all pending revisions, make everything normal + setIsPendingRevision(false); + } + } else if (msg.type == "NO_COMMIT_PENDING") { if (state == "COMMITTING") @@ -591,6 +669,11 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) schedulePerhapsCallIdleFuncs(); } + function setIsPendingRevision(value) + { + isPendingRevision = value; + } + function callWhenNotCommitting(func) { idleFuncs.push(func); @@ -656,7 +739,9 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) getMissedChanges: getMissedChanges, callWhenNotCommitting: callWhenNotCommitting, addHistoricalAuthors: tellAceAboutHistoricalAuthors, - setChannelState: setChannelState + setChannelState: setChannelState, + setStateIdle: setStateIdle, + setIsPendingRevision: setIsPendingRevision }; $(document).ready(setUpSocket); diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 8fcec23f..de613910 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -206,10 +206,12 @@ function handshake() socket.on('reconnect', function () { pad.collabClient.setChannelState("CONNECTED"); - pad.sendClientReady(true); + pad.sendClientReady(receivedClientVars); }); socket.on('reconnecting', function() { + pad.collabClient.setStateIdle(); + pad.collabClient.setIsPendingRevision(true); pad.collabClient.setChannelState("RECONNECTING"); }); @@ -217,6 +219,11 @@ function handshake() pad.collabClient.setChannelState("DISCONNECTED", "reconnect_timeout"); }); + socket.on('error', function(error) { + pad.collabClient.setStateIdle(); + pad.collabClient.setIsPendingRevision(true); + }); + var initalized = false; socket.on('message', function(obj) @@ -831,7 +838,7 @@ var pad = { $.ajax( { type: 'post', - url: '/ep/pad/connection-diagnostic-info', + url: 'ep/pad/connection-diagnostic-info', data: { diagnosticInfo: JSON.stringify(pad.diagnosticInfo) }, diff --git a/src/templates/export_html.html b/src/templates/export_html.html index b29941c9..b8893b71 100644 --- a/src/templates/export_html.html +++ b/src/templates/export_html.html @@ -139,6 +139,5 @@ ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol { <%- body %> -