From a2ed266048f2033e43c2c6e78cd10ad0bded3f70 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 30 Aug 2017 11:10:57 +0200 Subject: [PATCH 01/16] Move the code app in a secure iframe --- customize.dist/src/less/loading.less | 4 +- www/code2/code.less | 102 +++++ www/code2/index.html | 30 ++ www/code2/inner.html | 16 + www/code2/inner.js | 652 +++++++++++++++++++++++++++ www/code2/main.js | 50 ++ www/common/common-codemirror.js | 4 +- www/common/cryptpad-common.js | 1 + www/common/sframe-boot.js | 2 +- www/common/sframe-common-outer.js | 218 +++++++++ www/pad/inner.js | 4 +- www/pad/main.js | 201 +-------- 12 files changed, 1081 insertions(+), 203 deletions(-) create mode 100644 www/code2/code.less create mode 100644 www/code2/index.html create mode 100644 www/code2/inner.html create mode 100644 www/code2/inner.js create mode 100644 www/code2/main.js create mode 100644 www/common/sframe-common-outer.js diff --git a/customize.dist/src/less/loading.less b/customize.dist/src/less/loading.less index e7cb8060a..a9442d3cb 100644 --- a/customize.dist/src/less/loading.less +++ b/customize.dist/src/less/loading.less @@ -1,7 +1,7 @@ @import "./variables.less"; @import (once) "../less2/include/colortheme.less"; -.cp #loading { +#loading { position: fixed; z-index: 9999; top: 0px; @@ -33,7 +33,7 @@ } } } -.cp #loadingTip { +#loadingTip { position: fixed; z-index: 99999; top: 80%; diff --git a/www/code2/code.less b/www/code2/code.less new file mode 100644 index 000000000..36883f377 --- /dev/null +++ b/www/code2/code.less @@ -0,0 +1,102 @@ +@import "/customize/src/less/variables.less"; +@import "/customize/src/less/mixins.less"; +@import "/common/markdown.less"; +@import "/common/file-dialog.less"; + +html, body{ + height: 100%; + width: 100%; + padding: 0px; + margin: 0px; + overflow: hidden; + box-sizing: border-box; + position: relative; +} +body { + display: flex; + flex-flow: column; + max-height: 100%; + min-height: auto; +} + +@slideTime: 500ms; +.CodeMirror { + display: inline-block; + height: 100%; + width: 50%; + &.transition { + transition: width @slideTime, min-width @slideTime, max-width @slideTime; + } + min-width: 20%; + max-width: 80%; + resize: horizontal; + font-size: initial; +} +.CodeMirror.fullPage { + //min-width: 100%; + max-width: 100%; + resize: none; + flex: 1; +} +.CodeMirror-focused .cm-matchhighlight { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==); + background-position: bottom; + background-repeat: repeat-x; +} +#editorContainer { + flex: 1; + display: flex; + flex-flow: row; + height: 100%; + overflow: hidden; +} +#previewContainer { + flex: 1; + padding: 5px 20px; + overflow: auto; + display: inline-block; + height: 100%; + border-left: 1px solid black; + box-sizing: border-box; + font-family: Calibri,Ubuntu,sans-serif; + word-wrap: break-word; + position: relative; + media-tag { + * { + max-width:100%; + } + iframe[type="application/pdf"] { + max-height:50vh; + } + } +} + +#preview { + max-width: 40vw; + margin: 1em auto; + + .markdown_preformatted-code; + .markdown_gfm-table(black); +} + +.cp-splitter { + position: absolute; + height: 100%; + width: 8px; + top: 0; + left: 0; + + cursor: col-resize; +} + +@media (max-width: @media-medium-screen) { + .CodeMirror { + flex: 1; + max-width: 100%; + resize: none; + } + #previewContainer { + display: none !important; + } +} + diff --git a/www/code2/index.html b/www/code2/index.html new file mode 100644 index 000000000..8be90cfb5 --- /dev/null +++ b/www/code2/index.html @@ -0,0 +1,30 @@ + + + + CryptPad + + + + + + + + - + + diff --git a/www/oldcode/inner.html b/www/oldcode/inner.html new file mode 100644 index 000000000..99bec8d08 --- /dev/null +++ b/www/oldcode/inner.html @@ -0,0 +1,17 @@ + + + + + + + + + +
+
+ +
+
+ + + diff --git a/www/oldcode/inner.js b/www/oldcode/inner.js new file mode 100644 index 000000000..d36a7acd2 --- /dev/null +++ b/www/oldcode/inner.js @@ -0,0 +1,40 @@ +define([ + 'jquery', + + 'cm/lib/codemirror', + + 'css!/bower_components/components-font-awesome/css/font-awesome.min.css', + 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', + 'less!/code/code.less', + 'less!/customize/src/less/toolbar.less', + 'less!/customize/src/less/cryptpad.less', + + 'css!cm/lib/codemirror.css', + 'css!cm/addon/dialog/dialog.css', + 'css!cm/addon/fold/foldgutter.css', + + 'cm/mode/markdown/markdown', + 'cm/addon/mode/loadmode', + 'cm/mode/meta', + 'cm/addon/mode/overlay', + 'cm/addon/mode/multiplex', + 'cm/addon/mode/simple', + 'cm/addon/edit/closebrackets', + 'cm/addon/edit/matchbrackets', + 'cm/addon/edit/trailingspace', + 'cm/addon/selection/active-line', + 'cm/addon/search/search', + 'cm/addon/search/match-highlighter', + 'cm/addon/search/searchcursor', + 'cm/addon/dialog/dialog', + 'cm/addon/fold/foldcode', + 'cm/addon/fold/foldgutter', + 'cm/addon/fold/brace-fold', + 'cm/addon/fold/xml-fold', + 'cm/addon/fold/markdown-fold', + 'cm/addon/fold/comment-fold', + 'cm/addon/display/placeholder', +], function ($, CMeditor) { + window.CodeMirror = CMeditor; + $('.loading-hidden').removeClass('loading-hidden'); +}); diff --git a/www/oldcode/main.js b/www/oldcode/main.js new file mode 100644 index 000000000..5e06572b6 --- /dev/null +++ b/www/oldcode/main.js @@ -0,0 +1,559 @@ +define([ + 'jquery', + '/bower_components/chainpad-crypto/crypto.js', + '/bower_components/chainpad-netflux/chainpad-netflux.js', + '/bower_components/textpatcher/TextPatcher.js', + '/common/toolbar2.js', + 'json.sortify', + '/bower_components/chainpad-json-validator/json-ot.js', + '/common/cryptpad-common.js', + '/common/cryptget.js', + '/common/diffMarked.js', + + 'css!/bower_components/components-font-awesome/css/font-awesome.min.css', + 'less!/customize/src/less/cryptpad.less' +], function ($, Crypto, Realtime, TextPatcher, Toolbar, JSONSortify, JsonOT, Cryptpad, + Cryptget, DiffMd) { + var Messages = Cryptpad.Messages; + + var APP = window.APP = { + Cryptpad: Cryptpad, + }; + + $(function () { + Cryptpad.addLoadingScreen(); + + var ifrw = APP.ifrw = $('#pad-iframe')[0].contentWindow; + var stringify = function (obj) { + return JSONSortify(obj); + }; + + var toolbar; + var editor; + + var secret = Cryptpad.getSecrets(); + var readOnly = secret.keys && !secret.keys.editKeyStr; + if (!secret.keys) { + secret.keys = secret.key; + } + + var onConnectError = function () { + Cryptpad.errorLoadingScreen(Messages.websocketError); + }; + + var andThen = function (CMeditor) { + var $iframe = $('#pad-iframe').contents(); + var $contentContainer = $iframe.find('#editorContainer'); + var $previewContainer = $iframe.find('#previewContainer'); + var $preview = $iframe.find('#preview'); + $preview.click(function (e) { + if (!e.target) { return; } + var $t = $(e.target); + if ($t.is('a') || $t.parents('a').length) { + e.preventDefault(); + var $a = $t.is('a') ? $t : $t.parents('a').first(); + var href = $a.attr('href'); + window.open(href); + } + }); + + var CodeMirror = Cryptpad.createCodemirror(ifrw, Cryptpad, null, CMeditor); + $iframe.find('.CodeMirror').addClass('fullPage'); + editor = CodeMirror.editor; + + var setIndentation = APP.setIndentation = function (units, useTabs) { + if (typeof(units) !== 'number') { return; } + editor.setOption('indentUnit', units); + editor.setOption('tabSize', units); + editor.setOption('indentWithTabs', useTabs); + }; + + var indentKey = 'indentUnit'; + var useTabsKey = 'indentWithTabs'; + + var proxy = Cryptpad.getProxy(); + + var updateIndentSettings = APP.updateIndentSettings = function () { + var indentUnit = proxy.settings[indentKey]; + var useTabs = proxy.settings[useTabsKey]; + setIndentation( + typeof(indentUnit) === 'number'? indentUnit: 2, + typeof(useTabs) === 'boolean'? useTabs: false); + }; + + proxy.on('change', ['settings', indentKey], updateIndentSettings); + proxy.on('change', ['settings', useTabsKey], updateIndentSettings); + + var $bar = $('#pad-iframe')[0].contentWindow.$('#cme_toolbox'); + + var isHistoryMode = false; + + var setEditable = APP.setEditable = function (bool) { + if (readOnly && bool) { return; } + editor.setOption('readOnly', !bool); + }; + + var Title; + var UserList; + var Metadata; + + var config = { + initialState: '{}', + websocketURL: Cryptpad.getWebsocketURL(), + channel: secret.channel, + // our public key + validateKey: secret.keys.validateKey || undefined, + readOnly: readOnly, + crypto: Crypto.createEncryptor(secret.keys), + network: Cryptpad.getNetwork(), + transformFunction: JsonOT.validate, + }; + + var canonicalize = function (t) { return t.replace(/\r\n/g, '\n'); }; + + var setHistory = function (bool, update) { + isHistoryMode = bool; + setEditable(!bool); + if (!bool && update) { + config.onRemote(); + } + }; + + var initializing = true; + + var stringifyInner = function (textValue) { + var obj = { + content: textValue, + metadata: { + users: UserList.userData, + defaultTitle: Title.defaultTitle + } + }; + if (!initializing) { + obj.metadata.title = Title.title; + } + // set mode too... + obj.highlightMode = CodeMirror.highlightMode; + + // stringify the json and send it into chainpad + return stringify(obj); + }; + + var forceDrawPreview = function () { + try { + DiffMd.apply(DiffMd.render(editor.getValue()), $preview); + } catch (e) { console.error(e); } + }; + + var drawPreview = Cryptpad.throttle(function () { + if (CodeMirror.highlightMode !== 'markdown') { return; } + if (!$previewContainer.is(':visible')) { return; } + forceDrawPreview(); + }, 150); + + var onLocal = config.onLocal = function () { + if (initializing) { return; } + if (isHistoryMode) { return; } + if (readOnly) { return; } + + editor.save(); + + drawPreview(); + + var textValue = canonicalize(CodeMirror.$textarea.val()); + var shjson = stringifyInner(textValue); + + APP.patchText(shjson); + + if (APP.realtime.getUserDoc() !== shjson) { + console.error("realtime.getUserDoc() !== shjson"); + } + }; + + var mediaTagModes = [ + 'markdown', + 'html', + 'htmlembedded', + 'htmlmixed', + 'index.html', + 'php', + 'velocity', + 'xml', + ]; + + var onModeChanged = function (mode) { + var $codeMirror = $iframe.find('.CodeMirror'); + window.clearTimeout(APP.previewTo); + $codeMirror.addClass('transition'); + APP.previewTo = window.setTimeout(function () { + $codeMirror.removeClass('transition'); + }, 500); + if (mediaTagModes.indexOf(mode) !== -1) { + APP.$mediaTagButton.show(); + } else { APP.$mediaTagButton.hide(); } + + if (mode === "markdown") { + APP.$previewButton.show(); + Cryptpad.getPadAttribute('previewMode', function (e, data) { + if (e) { return void console.error(e); } + if (data !== false) { + $previewContainer.show(); + APP.$previewButton.addClass('active'); + $codeMirror.removeClass('fullPage'); + } + }); + return; + } + APP.$previewButton.hide(); + $previewContainer.hide(); + APP.$previewButton.removeClass('active'); + $codeMirror.addClass('fullPage'); + if (typeof(APP.updateIndentSettings) === 'function') { + APP.updateIndentSettings(); + } + }; + + config.onInit = function (info) { + UserList = Cryptpad.createUserList(info, config.onLocal, Cryptget, Cryptpad); + + var titleCfg = { getHeadingText: CodeMirror.getHeadingText }; + Title = Cryptpad.createTitle(titleCfg, config.onLocal, Cryptpad); + + Metadata = Cryptpad.createMetadata(UserList, Title, null, Cryptpad); + + var configTb = { + displayed: ['title', 'useradmin', 'spinner', 'lag', 'state', 'share', 'userlist', 'newpad', 'limit', 'upgrade'], + userList: UserList.getToolbarConfig(), + share: { + secret: secret, + channel: info.channel + }, + title: Title.getTitleConfig(), + common: Cryptpad, + readOnly: readOnly, + ifrw: ifrw, + realtime: info.realtime, + network: info.network, + $container: $bar, + $contentContainer: $contentContainer + }; + toolbar = APP.toolbar = Toolbar.create(configTb); + + Title.setToolbar(toolbar); + CodeMirror.init(config.onLocal, Title, toolbar); + + var $rightside = toolbar.$rightside; + var $drawer = toolbar.$drawer; + + var editHash; + if (!readOnly) { + editHash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys); + } + + /* add a history button */ + var histConfig = { + onLocal: config.onLocal, + onRemote: config.onRemote, + setHistory: setHistory, + applyVal: function (val) { + var remoteDoc = JSON.parse(val || '{}').content; + editor.setValue(remoteDoc || ''); + editor.save(); + }, + $toolbar: $bar + }; + var $hist = Cryptpad.createButton('history', true, {histConfig: histConfig}); + $drawer.append($hist); + + /* save as template */ + if (!Cryptpad.isTemplate(window.location.href)) { + var templateObj = { + rt: info.realtime, + Crypt: Cryptget, + getTitle: Title.getTitle + }; + var $templateButton = Cryptpad.createButton('template', true, templateObj); + $rightside.append($templateButton); + } + + /* add an export button */ + var $export = Cryptpad.createButton('export', true, {}, CodeMirror.exportText); + $drawer.append($export); + + if (!readOnly) { + /* add an import button */ + var $import = Cryptpad.createButton('import', true, {}, CodeMirror.importText); + $drawer.append($import); + } + + /* add a forget button */ + var forgetCb = function (err) { + if (err) { return; } + setEditable(false); + }; + var $forgetPad = Cryptpad.createButton('forget', true, {}, forgetCb); + $rightside.append($forgetPad); + + var fileDialogCfg = { + $body: $iframe.find('body'), + onSelect: function (href) { + var parsed = Cryptpad.parsePadUrl(href); + var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel); + var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName; + var mt = ''; + editor.replaceSelection(mt); + }, + data: APP + }; + APP.$mediaTagButton = $('