You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by wa...@apache.org on 2022/05/11 11:34:41 UTC
[echarts-examples] branch gh-pages updated: enhance sandbox security and optimize share hint toast
This is an automated email from the ASF dual-hosted git repository.
wangzx pushed a commit to branch gh-pages
in repository https://gitbox.apache.org/repos/asf/echarts-examples.git
The following commit(s) were added to refs/heads/gh-pages by this push:
new 967dc5f4 enhance sandbox security and optimize share hint toast
967dc5f4 is described below
commit 967dc5f4398de3531d2d1b78450c521cfa1ddb0c
Author: plainheart <yh...@all-my-life.cn>
AuthorDate: Wed May 11 19:33:19 2022 +0800
enhance sandbox security and optimize share hint toast
Signed-off-by: plainheart <yh...@all-my-life.cn>
---
src/editor/Editor.vue | 13 -------
src/editor/Preview.vue | 11 +++---
src/editor/View.vue | 18 ---------
src/editor/downloadExample.js | 4 +-
src/editor/sandbox/setup.js | 91 +++++++++++++++++++++++++++++++++----------
5 files changed, 79 insertions(+), 58 deletions(-)
diff --git a/src/editor/Editor.vue b/src/editor/Editor.vue
index 6797a3f0..a14442e6 100644
--- a/src/editor/Editor.vue
+++ b/src/editor/Editor.vue
@@ -251,7 +251,6 @@ export default {
loadExampleCode().then((code) => {
// No editor available. Set to runCode directly.
store.runCode = parseSourceCode(code);
- this.showShareHint();
});
} else {
loadExampleCode().then((code) => {
@@ -260,7 +259,6 @@ export default {
if (store.initialCode !== CODE_CHANGED_FLAG) {
store.initialCode = this.initialCode;
}
- this.showShareHint();
});
window.addEventListener('mousemove', (e) => {
@@ -278,17 +276,6 @@ export default {
},
methods: {
- showShareHint() {
- if (store.isSharedCode) {
- this.$message.closeAll();
- this.$message({
- type: 'warning',
- message: this.$t('editor.share.hint'),
- duration: 5000,
- showClose: true
- });
- }
- },
toExternalEditor(vendor) {
const previewRef = this.$refs.preview;
if (!previewRef) {
diff --git a/src/editor/Preview.vue b/src/editor/Preview.vue
index 2dafe445..889933f1 100644
--- a/src/editor/Preview.vue
+++ b/src/editor/Preview.vue
@@ -329,9 +329,6 @@ export default {
mounted() {
this.run();
- if (store.isSharedCode) {
- this.showShareHint();
- }
this.fetchVersionList();
},
@@ -368,6 +365,8 @@ export default {
if (!this.debouncedRun) {
// First run
this.run();
+ // show share hint on first run if code is user-shared
+ store.isSharedCode && this.showShareHint();
} else {
this.debouncedRun();
}
@@ -406,7 +405,9 @@ export default {
this.sandbox = null;
}
},
- download,
+ download() {
+ download(store.isSharedCode && this.$t('editor.share.hint'));
+ },
screenshot() {
this.sandbox &&
this.sandbox.screenshot(
@@ -421,7 +422,7 @@ export default {
type: 'warning',
message: this.$t('editor.share.hint'),
customClass: 'toast-shared-url',
- duration: 5000,
+ duration: 8000,
showClose: true
});
},
diff --git a/src/editor/View.vue b/src/editor/View.vue
index 6b436641..e6e96ad1 100644
--- a/src/editor/View.vue
+++ b/src/editor/View.vue
@@ -15,24 +15,6 @@ export default {
loadExampleCode().then((code) => {
store.runCode = parseSourceCode(code);
});
-
- this.showShareHint();
- },
-
- methods: {
- showShareHint() {
- if (store.isSharedCode) {
- this.$message.closeAll();
- this.$message({
- type: 'warning',
- message: this.$t('editor.share.hint'),
- duration: 5000,
- showClose: true
- });
- }
- }
}
};
</script>
-
-<style lang="scss"></style>
diff --git a/src/editor/downloadExample.js b/src/editor/downloadExample.js
index de3dc386..f33d12ec 100644
--- a/src/editor/downloadExample.js
+++ b/src/editor/downloadExample.js
@@ -2,7 +2,7 @@ import { store } from '../common/store';
import { URL_PARAMS, SCRIPT_URLS } from '../common/config';
import { downloadBlob } from '../common/helper';
-export function download() {
+export function download(shareHint) {
const hasRootPath = store.sourceCode.indexOf('ROOT_PATH') > -1;
const rootPathCode = hasRootPath ? `var ROOT_PATH = '${store.cdnRoot}';` : '';
const lang = store.locale && store.locale.indexOf('zh') > -1 ? 'zh-CN' : 'en';
@@ -18,7 +18,7 @@ export function download() {
);
const echarts4Dir = SCRIPT_URLS.echartsDir.replace('{{version}}', '4.9.0');
const code = `<!--
- THIS EXAMPLE WAS DOWNLOADED FROM ${window.location.href}
+ ${shareHint || `THIS EXAMPLE WAS DOWNLOADED FROM ${window.location.href}`}
-->
<!DOCTYPE html>
<html lang="${lang}" style="height: 100%">
diff --git a/src/editor/sandbox/setup.js b/src/editor/sandbox/setup.js
index 4ed795e5..ed889d56 100644
--- a/src/editor/sandbox/setup.js
+++ b/src/editor/sandbox/setup.js
@@ -84,8 +84,51 @@ function setup(isShared) {
{
location: Object.freeze(JSON.parse(JSON.stringify(location))),
document: (() => {
- const nativeCreateElement = document.createElement;
- const nativeCreateElementNS = document.createElementNS;
+ const disallowedElements = [
+ 'script',
+ 'video',
+ 'audio',
+ 'iframe',
+ 'frame',
+ 'frameset',
+ 'embed',
+ 'object',
+ // PENDING
+ 'foreignobject'
+ ];
+ const disallowedElementsMatcher = new RegExp(
+ `<(${disallowedElements.join('|')}).*>`
+ );
+ const nativeSetters = {
+ innerHTML: Object.getOwnPropertyDescriptor(
+ Element.prototype,
+ 'innerHTML'
+ ).set,
+ outerHTML: Object.getOwnPropertyDescriptor(
+ Element.prototype,
+ 'outerHTML'
+ ).set,
+ innerText: Object.getOwnPropertyDescriptor(
+ HTMLElement.prototype,
+ 'innerText'
+ ).set,
+ outerText: Object.getOwnPropertyDescriptor(
+ HTMLElement.prototype,
+ 'outerText'
+ ).set
+ };
+ ['inner', 'outer'].forEach((prop) => {
+ const htmlProp = prop + 'HTML';
+ Object.defineProperty(Element.prototype, htmlProp, {
+ set(value) {
+ return (
+ disallowedElementsMatcher.test(value)
+ ? nativeSetters[prop + 'Text']
+ : nativeSetters[htmlProp]
+ ).call(this, value);
+ }
+ });
+ });
const fakeDoc = document.cloneNode();
// To enable the created elements to be inserted to body
// Object.defineProperties(fakeDoc, {
@@ -100,24 +143,32 @@ function setup(isShared) {
// }
// }
// });
- fakeDoc.createElement = function () {
- const tagName = arguments[0];
- if (tagName && tagName.toLowerCase() === 'script') {
- return console.error(
- `Disallowed attempting to create dynamic script!`
- );
- }
- return nativeCreateElement.apply(document, arguments);
- };
- fakeDoc.nativeCreateElementNS = function () {
- const tagName = arguments[0];
- if (tagName && tagName.toLowerCase() === 'script') {
- return console.error(
- `Disallowed attempting to create dynamic script!`
- );
- }
- return nativeCreateElementNS.apply(document, arguments);
- };
+ [
+ ['write', document.write, 0, true],
+ ['writeln', document.writeln, 0, true],
+ ['createElement', document.createElement, 0],
+ ['createElementNS', document.createElementNS, 1]
+ ].forEach((api) => {
+ const nativeFn = api[1];
+ const argIndx = api[2];
+ const fullTextSearch = api[3];
+ fakeDoc[api[0]] = function () {
+ let val = arguments[argIndx];
+ val && (val = val.toLowerCase());
+ if (
+ val &&
+ (fullTextSearch
+ ? ((val = val.match(disallowedElementsMatcher)),
+ (val = val && val[1]))
+ : disallowedElements.includes(val))
+ ) {
+ return console.error(
+ `Disallowed attempting to create ${val} element!`
+ );
+ }
+ return nativeFn.apply(document, arguments);
+ };
+ });
return fakeDoc;
})(),
history: void 0,
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org