aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js
diff options
context:
space:
mode:
Diffstat (limited to 'web/src/js')
-rw-r--r--web/src/js/certinstall.jsx27
-rw-r--r--web/src/js/datastructures.js101
-rw-r--r--web/src/js/footer.react.js12
-rw-r--r--web/src/js/header.react.js73
-rw-r--r--web/src/js/mitmproxy.js10
-rw-r--r--web/src/js/mitmproxy.react.js60
-rw-r--r--web/src/js/router.jsx10
7 files changed, 246 insertions, 47 deletions
diff --git a/web/src/js/certinstall.jsx b/web/src/js/certinstall.jsx
deleted file mode 100644
index 2e681ac2..00000000
--- a/web/src/js/certinstall.jsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/** @jsx React.DOM */
-
-var CertInstallView = React.createClass({
- render: function () {
- return <div className="certinstall">
- <h2> Click to install the mitmproxy certificate: </h2>
- <div id="certbank" className="row">
- <div className="col-md-3">
- <a href="/cert/pem"><i className="fa fa-apple fa-5x"></i></a>
- <p>Apple</p>
- </div>
- <div className="col-md-3">
- <a href="/cert/p12"><i className="fa fa-windows fa-5x"></i></a>
- <p>Windows</p>
- </div>
- <div className="col-md-3">
- <a href="/cert/pem"><i className="fa fa-android fa-5x"></i></a>
- <p>Android</p>
- </div>
- <div className="col-md-3">
- <a href="/cert/pem"><i className="fa fa-asterisk fa-5x"></i></a>
- <p>Other</p>
- </div>
- </div>
- </div>;
- }
-});
diff --git a/web/src/js/datastructures.js b/web/src/js/datastructures.js
new file mode 100644
index 00000000..59f64e66
--- /dev/null
+++ b/web/src/js/datastructures.js
@@ -0,0 +1,101 @@
+class EventEmitter {
+ constructor(){
+ this._listeners = {};
+ }
+ emit(event){
+ if(!(event in this._listeners)){
+ return;
+ }
+ this._listeners[event].forEach(function (listener) {
+ listener(event, this);
+ }.bind(this));
+ }
+ addListener(event, f){
+ this._listeners[event] = this._listeners[event] || [];
+ this._listeners[event].push(f);
+ }
+ removeListener(event, f){
+ if(!(event in this._listeners)){
+ return false;
+ }
+ var index = this._listeners.indexOf(f);
+ if (index >= 0) {
+ this._listeners.splice(this._listeners.indexOf(f), 1);
+ }
+ }
+}
+
+var FLOW_CHANGED = "flow.changed";
+
+class FlowStore extends EventEmitter{
+ constructor() {
+ super();
+ this.flows = [];
+ this._listeners = [];
+ }
+
+ getAll() {
+ return this.flows;
+ }
+
+ emitChange() {
+ return this.emit(FLOW_CHANGED);
+ }
+
+ addChangeListener(f) {
+ this.addListener(FLOW_CHANGED, f);
+ }
+
+ removeChangeListener(f) {
+ this.removeListener(FLOW_CHANGED, f);
+ }
+}
+
+class DummyFlowStore extends FlowStore {
+ constructor(flows) {
+ super();
+ this.flows = flows;
+ }
+
+ addFlow(f) {
+ this.flows.push(f);
+ this.emitChange();
+ }
+}
+
+
+SETTINGS_CHANGED = "settings.change";
+
+class Settings extends EventEmitter {
+ constructor(){
+ super();
+ this.settings = false;
+ }
+
+ getAll(){
+ return this.settings;
+ }
+
+ emitChange() {
+ return this.emit(SETTINGS_CHANGED);
+ }
+
+ addChangeListener(f) {
+ this.addListener(SETTINGS_CHANGED, f);
+ }
+
+ removeChangeListener(f) {
+ this.removeListener(SETTINGS_CHANGED, f);
+ }
+}
+
+class DummySettings extends Settings {
+ constructor(settings){
+ super();
+ this.settings = settings;
+ }
+ update(obj){
+ _.merge(this.settings, obj);
+ this.emitChange();
+ }
+} \ No newline at end of file
diff --git a/web/src/js/footer.react.js b/web/src/js/footer.react.js
new file mode 100644
index 00000000..96506e85
--- /dev/null
+++ b/web/src/js/footer.react.js
@@ -0,0 +1,12 @@
+/** @jsx React.DOM */
+
+var Footer = React.createClass({
+ render : function(){
+ var style = {
+ textAlign: "center"
+ };
+ return (<footer>
+ <span className="label label-success">transparent mode</span>
+ </footer>);
+ }
+}); \ No newline at end of file
diff --git a/web/src/js/header.react.js b/web/src/js/header.react.js
new file mode 100644
index 00000000..b204eeb8
--- /dev/null
+++ b/web/src/js/header.react.js
@@ -0,0 +1,73 @@
+/** @jsx React.DOM */
+
+var MainMenu = React.createClass({
+ render : function(){
+ return (<div>Main Menu</div>);
+ }
+});
+var ToolsMenu = React.createClass({
+ render : function(){
+ return (<div>Tools Menu</div>);
+ }
+});
+var ReportsMenu = React.createClass({
+ render : function(){
+ return (<div>Reports Menu</div>);
+ }
+});
+
+var _Header_Entries = {
+ main: {
+ title: "Traffic",
+ route: "main",
+ menu: MainMenu
+ },
+ tools: {
+ title: "Tools",
+ route: "main",
+ menu: ToolsMenu
+ },
+ reports: {
+ title: "Visualization",
+ route: "reports",
+ menu: ReportsMenu
+ }
+};
+
+var Header = React.createClass({
+ getInitialState: function(){
+ return {active: "main"};
+ },
+ handleClick: function(active){
+ this.setState({active: active});
+ ReactRouter.transitionTo(_Header_Entries[active].route);
+ return false;
+ },
+ handleFileClick: function(){
+ console.log("File click");
+ },
+ render: function(){
+
+ var header = [];
+ for(var item in _Header_Entries){
+ var classes = this.state.active == item ? "active" : "";
+ header.push(<a key={item} href="#" className={classes}
+ onClick={this.handleClick.bind(this, item)}>{ _Header_Entries[item].title }</a>);
+ }
+
+ var menu = _Header_Entries[this.state.active].menu();
+ return (
+ <header>
+ <div className="title-bar">
+ mitmproxy { this.props.settings.version }
+ </div>
+ <nav>
+ <a href="#" className="special" onClick={this.handleFileClick}> File </a>
+ {header}
+ </nav>
+ <div className="menu">
+ { menu }
+ </div>
+ </header>);
+ }
+}); \ No newline at end of file
diff --git a/web/src/js/mitmproxy.js b/web/src/js/mitmproxy.js
deleted file mode 100644
index a8e55065..00000000
--- a/web/src/js/mitmproxy.js
+++ /dev/null
@@ -1,10 +0,0 @@
-
-mitmproxy = function () {
- function init() {
- React.renderComponent(Router(), $("#mitmproxy")[0]);
- }
- var exports = {
- init: init,
- };
- return exports;
-}();
diff --git a/web/src/js/mitmproxy.react.js b/web/src/js/mitmproxy.react.js
new file mode 100644
index 00000000..2a2ee910
--- /dev/null
+++ b/web/src/js/mitmproxy.react.js
@@ -0,0 +1,60 @@
+/** @jsx React.DOM */
+
+var App = React.createClass({
+ getInitialState: function () {
+ return {
+ settings: {} //TODO: How explicit should we get here?
+ //List all subattributes?
+ };
+ },
+ componentDidMount: function () {
+ //TODO: Replace DummyStore with real settings over WS (https://facebook.github.io/react/tips/initial-ajax.html)
+ //TODO: Is there a sensible place where we can store this?
+ var settings = new DummySettings({
+ version: "0.12"
+ });
+ settings.addChangeListener(this._onSettingsChange);
+
+ //This would be async in some way or another.
+ this._onSettingsChange(null, settings);
+ },
+ _onSettingsChange: function(event, settings){
+ this.setState({settings: settings.getAll()});
+ },
+ render: function () {
+ return (
+ <div id="container">
+ <Header settings={this.state.settings}/>
+ <div id="main">
+ <this.props.activeRouteHandler settings={this.state.settings}/>
+ </div>
+ <Footer/>
+ </div>
+ );
+ }
+});
+
+var Traffic = React.createClass({
+ render: function(){
+ var json = JSON.stringify(this.props, null, 4);
+ var i = 5;
+ while(i--) json += json;
+ return (<pre>{json}</pre>);
+ }
+});
+
+var Reports = React.createClass({
+ render: function(){
+ return (<div>Report Editor</div>);
+ }
+});
+
+var routes = (
+ <ReactRouter.Routes location="hash">
+ <ReactRouter.Route name="app" path="/" handler={App}>
+ <ReactRouter.Route name="main" handler={Traffic}/>
+ <ReactRouter.Route name="reports" handler={Reports}/>
+ <ReactRouter.Redirect to="main"/>
+ </ReactRouter.Route>
+ </ReactRouter.Routes>
+); \ No newline at end of file
diff --git a/web/src/js/router.jsx b/web/src/js/router.jsx
deleted file mode 100644
index dc3e729b..00000000
--- a/web/src/js/router.jsx
+++ /dev/null
@@ -1,10 +0,0 @@
-/** @jsx React.DOM */
-
-var Router = React.createClass({
- render: function(){
- return <ReactRouter.Routes location="hash">
- <ReactRouter.Route name="certs" path="/" handler={CertInstallView}/>
- <ReactRouter.Route name="other" path="/other" handler={CertInstallView}/>
- </ReactRouter.Routes>;
- }
-});