From d3d13f101a45dace9ca7eb5291d3d51dfb315d84 Mon Sep 17 00:00:00 2001 From: Emiliano Ciavatta Date: Fri, 2 Oct 2020 23:35:12 +0200 Subject: Add render_html feature --- frontend/package.json | 1 + frontend/src/components/ConnectionContent.js | 67 +++++++++++++++++++++------- frontend/yarn.lock | 5 +++ 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index b13a7ea..a2d4166 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ "bootstrap": "^4.4.1", "bs-custom-file-input": "^1.3.4", "classnames": "^2.2.6", + "dompurify": "^2.1.1", "eslint-config-react-app": "^5.2.1", "lodash": "^4.17.20", "node-sass": "^4.14.0", diff --git a/frontend/src/components/ConnectionContent.js b/frontend/src/components/ConnectionContent.js index ccaec0b..8667886 100644 --- a/frontend/src/components/ConnectionContent.js +++ b/frontend/src/components/ConnectionContent.js @@ -5,6 +5,7 @@ import MessageAction from "./MessageAction"; import backend from "../backend"; import ButtonField from "./fields/ButtonField"; import ChoiceField from "./fields/ChoiceField"; +import DOMPurify from 'dompurify'; const classNames = require('classnames'); @@ -21,7 +22,6 @@ class ConnectionContent extends Component { }; this.validFormats = ["default", "hex", "hexdump", "base32", "base64", "ascii", "binary", "decimal", "octal"]; - this.setFormat = this.setFormat.bind(this); } componentDidMount() { @@ -33,10 +33,15 @@ class ConnectionContent extends Component { componentDidUpdate(prevProps, prevState, snapshot) { if (this.props.connection != null && ( this.props.connection !== prevProps.connection || this.state.format !== prevState.format)) { + this.closeRenderWindow(); this.loadStream(); } } + componentWillUnmount() { + this.closeRenderWindow(); + } + loadStream = () => { this.setState({loading: true}); // TODO: limit workaround. @@ -48,13 +53,13 @@ class ConnectionContent extends Component { }); }; - setFormat(format) { + setFormat = (format) => { if (this.validFormats.includes(format)) { this.setState({format: format}); } - } + }; - tryParseConnectionMessage(connectionMessage) { + tryParseConnectionMessage = (connectionMessage) => { if (connectionMessage.metadata == null) { return connectionMessage.content; } @@ -87,22 +92,52 @@ class ConnectionContent extends Component { default: return connectionMessage.content; } - } + }; - connectionsActions(connectionMessage) { - if (connectionMessage.metadata == null || connectionMessage.metadata["reproducers"] === undefined) { + connectionsActions = (connectionMessage) => { + if (connectionMessage.metadata == null) { //} || !connectionMessage.metadata["reproducers"]) { return null; } - return Object.entries(connectionMessage.metadata["reproducers"]).map(([actionName, actionValue]) => - { - this.setState({ - messageActionDialog: this.setState({messageActionDialog: null})}/> - }); - }} /> - ); - } + const m = connectionMessage.metadata; + switch (m.type) { + case "http-request" : + if (!connectionMessage.metadata["reproducers"]) { + return; + } + return Object.entries(connectionMessage.metadata["reproducers"]).map(([actionName, actionValue]) => + { + this.setState({ + messageActionDialog: this.setState({messageActionDialog: null})}/> + }); + }} /> + ); + case "http-response": + if (m.headers && m.headers["Content-Type"].includes("text/html")) { + return { + let w; + if (this.state.renderWindow && !this.state.renderWindow.closed) { + w = this.state.renderWindow; + } else { + w = window.open("", "", "width=900, height=600, scrollbars=yes"); + this.setState({renderWindow: w}); + } + w.document.body.innerHTML = DOMPurify.sanitize(m.body); + w.focus(); + }} />; + } + break; + default: + return null; + } + }; + + closeRenderWindow = () => { + if (this.state.renderWindow) { + this.state.renderWindow.close(); + } + }; render() { let content = this.state.connectionContent; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 6d111a3..0a754ad 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -4068,6 +4068,11 @@ domhandler@^2.3.0: dependencies: domelementtype "1" +dompurify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.1.1.tgz#b5aa988676b093a9c836d8b855680a8598af25fe" + integrity sha512-NijiNVkS/OL8mdQL1hUbCD6uty/cgFpmNiuFxrmJ5YPH2cXrPKIewoixoji56rbZ6XBPmtM8GA8/sf9unlSuwg== + domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" -- cgit v1.2.3-70-g09d2