<commit_before><!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>National Cybersecurity Laboratories - Network Topology Tool</title>

    <link rel="shortcut icon" href="images/ncl_favicon1.png" th:href="@{~/images/ncl_favicon1.png}"/>
    <link rel="stylesheet" type="text/css" th:href="@{~/css/bootstrap.min.css}" media="screen"/>
    <link rel="stylesheet" type="text/css" th:href="@{~/css/font-awesome/css/font-awesome.min.css}"/>

    <style>
        html, body {
            height: 100%;
        }
        body {
            overflow: hidden;
        }
        .parent {
            height: 95%;
        }
        #icons_div, #results_div {
            height: 100%;
            overflow-y: scroll;
        }
        #paint_div {
            height: 100%;
            overflow: scroll;
        }
        #paintarea:focus {
            outline: none;
        }
        #ns2_text, #log_text {
            white-space: pre;
            overflow: scroll;
        }
    </style>

    <!-- common, all times required, imports -->
    <script th:src="@{~/topology-tool/wz_jsgraphics.js}"></script>
    <script th:src="@{~/topology-tool/draw2d.js}"></script>

    <!-- demo specific imports -->
    <script th:src="@{~/topology-tool/ResizeImage.js}"></script>
    <script th:src="@{~/topology-tool/ContextmenuConnection.js}"></script>
    <script th:src="@{~/topology-tool/MyInputPort.js}"></script>
    <script th:src="@{~/topology-tool/MyOutputPort.js}"></script>
    <script th:src="@{~/topology-tool/JSONSerializer.js}"></script>
    <script th:src="@{~/topology-tool/DiagramFigure.js}"></script>
    <script th:src="@{~/topology-tool/dom-to-image.min.js}"></script>

    <script type="text/javascript" th:src="@{~/topology-tool/adapter/prototype/prototype.js}"></script>
    <script type="text/javascript" th:src="@{~/js/jquery.min.js}"></script>
    <script type="text/javascript" th:src="@{~/js/bootstrap.min.js}"></script>

    <!--
    References:
    [1] http://learn.jquery.com/using-jquery-core/avoid-conflicts-other-libraries/
    [2] https://www.contrid.co.za/2015/06/fix-bootstrap-3-and-prototype-js-conflict/
    -->
    <script type="text/javascript">
        /*<![CDATA[*/
        var $j = jQuery.noConflict();
        if (Prototype.BrowserFeatures.ElementExtensions) {
            var disablePrototypeJS = function (method, pluginsToDisable) {
                    var handler = function (event) {
                        event.target[method] = undefined;
                        setTimeout(function () {
                            delete event.target[method];
                        }, 0);
                    };
                    pluginsToDisable.each(function (plugin) {
                        jQuery(window).on(method + '.bs.' + plugin, handler);
                    });
                },
                pluginsToDisable = ['collapse', 'dropdown', 'modal', 'tooltip', 'popover', 'tab'];
            disablePrototypeJS('show', pluginsToDisable);
            disablePrototypeJS('hide', pluginsToDisable);
        }
        /*]]>*/
    </script>

    <!-- use this imports if you want use the Yahoo utility methods -->
    <script type="text/javascript" th:src="@{~/topology-tool/adapter/yui/yui-utilities.js}"></script>
    <script type="text/javascript" th:src="@{~/topology-tool/adapter/yui/ext-yui-adapter.js}"></script>
    <script type="text/javascript" th:src="@{~/topology-tool/ext-all.js}"></script>

    <script type="text/javascript">
        /*<![CDATA[*/
        function createNewDiv(aID) {
            var txt = document.createElement('P');
            var div = document.createElement('span');
            div.setAttribute('id', aID);
            txt.setAttribute('id', aID + "_txt");
            div.appendChild(txt);
            return div;
        }

        function loadJSONtext(aText) {
            new JSONSerializer().fromJSON(Ext.util.JSON.decode(aText));
        }

        function addDragIconPic(aName, aWhere, aPic, aDisplay) {
            if (document.getElementById("cont_" + aName)) {
                return;
            }
            var div = document.getElementById(aWhere);
            var cdiv = createNewDiv("cont_" + aName);
            var html = '';
            html = html + "<center>";
            html = html + "<h1>" + aDisplay + "</h1>\n";
            html = html + "<img src='" + aPic + "' id='drag_" + aName + "' style='cursor:move'/>\n";
            html = html + "<hr size=1 noshade>\n";
            html = html + "</center>";

            cdiv.innerHTML = html;
            div.appendChild(cdiv);
            var dragsource = new Ext.dd.DragSource('drag_' + aName, {
                ddGroup: 'TreeDD',
                dragData: {name: 'DiagramFigure', type: aName, pic: aPic}
            });
        }

        function addDragIcon2(aName, aWhere, aDisplay) {
            var aPic = "/topology-tool/icons/" + aName + ".png";
            addDragIconPic(aName, aWhere, aPic, aDisplay);
        }

        function addLibraryIcon(aName, aDisplay) {
            if(aDisplay == undefined) aDisplay = aName;
            addDragIcon2(aName, "icons_div", aDisplay);
        }

        function createNewIconDiv(aID) {
            var txt = document.createElement('P');
            var div = document.createElement('span');
            div.setAttribute('id', aID);
            txt.setAttribute('id', aID + "_txt");
            div.appendChild(txt);
            document.getElementById("icons_div").appendChild(div);
            return div;
        }

        function doSendJSON() {
            var str = $j.trim($j('#json_text').val());
            if (!str) {
                alert("Please save topology to json before analysing.");
            } else {
                $j('#ns2_text').val("");
                $j('#log_text').val("");
                $j.post("/networkTool", { jsonText: str.replace("json_diagram = ", "") })
                    .done(function(data) {
                        var jsonData = $j.parseJSON(data);
                        $j('#ns2_text').val(jsonData.nsText.replace(/&#010;/g, "\n"));
                        $j('#log_text').val(jsonData.logText.replace(/&#010;/g, "\n"));
                    })
                    .fail(function(error) { debug(error); });
            }
        }

        function doSaveJSON() {
            var txt = Ext.util.JSON.encode(new JSONSerializer().toJSON(workflow.getDocument()));
            txt = txt.replace(/,"/g, ', "');
            document.getElementById('json_text').value = txt + "\n\n\n\n";
        }

        function doLoadJSON() {
            document.getElementById('paintarea').innerHTML = "";
            workflow = new Workflow('paintarea');
            workflow.scrollArea = document.getElementById("paint_div");
            loadJSONtext(document.getElementById('json_text').value);
        }

        // To enable function click() in Firefox
        HTMLElement.prototype.click = function() {
            var evt = this.ownerDocument.createEvent('MouseEvents');
            evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
            this.dispatchEvent(evt);
        }

        function doExportDiagramToImage() {
            var BORDERSIZE = 20;
            var $nodes = jQuery('#paintarea').children();

            if ($nodes.length <= 0) {
                alert("There is no diagram to export.");
                return;
            }

            // Find offset and bounds
            var left = Infinity;
            var top = Infinity;
            var right = 0;
            var bottom = 0;
            $nodes.each(function(index, node) {
                var $node = jQuery(node);
                var zIndex = $node.css('zIndex');
                // Calculate bounds for all nodes except line groups
                if (zIndex != '20') {
                    var pos = $node.position();
                    var posRight = pos.left + $node[0].scrollWidth;
                    var posBottom = pos.top + $node[0].scrollHeight;
                    left = (pos.left < left) ? pos.left : left;
                    top = (pos.top < top) ? pos.top : top;
                    right = (posRight > right) ? posRight : right;
                    bottom = (posBottom > bottom) ? posBottom : bottom;
                }
            });

            // Offset all nodes to origin
            $nodes.each(function(index, node) {
                var $node = jQuery(node);
                var pos = $node.position();
                $node.css({ left: pos.left - left + BORDERSIZE, top: pos.top - top + BORDERSIZE });
            });

            domtoimage.toJpeg(document.getElementById('paintarea'), { 
                    filter: function(node) {
                        // Exclude link anchor points
                        return (node.tagName !== 'DIV' || 
                                    (jQuery(node).css('zIndex') != '5000' && 
                                    jQuery(node).css('zIndex') != '10000'));
                    },
                    width: (right - left + BORDERSIZE*2) * window.devicePixelRatio,
                    height: (bottom - top + BORDERSIZE*2) * window.devicePixelRatio,
                    bgcolor: 'white',
                })
                .then(function(dataUrl) {
                    // Download as image
                    var link = document.createElement('a');
                    link.download = 'network-diagram.jpg';
                    link.href = dataUrl;
                    link.click();
                })
                .catch(function(error) {
                    console.error('Oops, something went wrong!', error);
                })
                .finally(function() {
                    // Revert the offset from origin
                    $nodes.each(function(index, node) {
                        var $node = jQuery(node);
                        var pos = $node.position();
                        $node.css({ left: pos.left + left - BORDERSIZE, top: pos.top + top - BORDERSIZE });
                    });
                });
        }

        function debug(message) {
            console.log(message);
        }
        /*]]>*/
    </script>
</head>
<body class="mybg loginbackground">
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" th:href="@{/}"><img src="/images/ncl_favicon1.png" alt="logo" width="20" class="logo1" /></a>
        </div>
        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <!--li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">File <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#"><i class="fa fa-file-text-o"></i> Open</a></li>
                        <li><a href="#"><i class="fa fa-floppy-o"></i> Save</a></li>
                    </ul>
                </li-->
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Library <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Physical Node</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Internet</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Kali</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Windows 7</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Router</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Windows 10</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Ubuntu 16</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Template <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#"><i class="fa fa-check" style="visibility:hidden"></i> 2 nodes</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:hidden"></i> 3 nodes</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">JSON <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#" onclick="doLoadJSON();"><i class="fa fa-upload"></i> Load</a></li>
                        <li><a href="#" onclick="doSaveJSON();"><i class="fa fa-download"></i> Save</a></li>
                        <li><a href="#" onclick="doSendJSON();"><i class="fa fa-cloud-upload"></i> Analyze</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Export <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#" onclick="doExportDiagramToImage();"><i class="fa fa-file-image-o"></i> Diagram As Image (.JPG)</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Help <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#" data-toggle="modal" data-target="#helpModal"><i class="fa fa-question"></i> Help</a></li>
                        <li><a href="#" data-toggle="modal" data-target="#aboutModal"><i class="fa fa-info"></i> About</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>
<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel" id="helpModal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">How to use</h4>
            </div>
            <div class="modal-body">
                <ul>
                    <li>Drag and drop. Connect the blue dots with lines. Double-click to add the annotations.</li>
                    <li>Control-drag the blue dots to clone them. Click on the unchecked links in the "Library" to add icons.</li>
                    <li>"Save" JSON into the textbox. "Load" JSON from the textbox. "Analyze" JSON to get the NS file and other associated files.</li>
                </ul>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="aboutModalLabel" id="aboutModal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">About</h4>
            </div>
            <div class="modal-body">
                <p>
                    This little hack is standing on the shoulders of giants:
                </p>
                <ul>
                    <li><a href="http://draw2d.org/">Draw2D library</a></li>
                    <li><a href="http://www.walterzorn.com/">Walter Zorn's JS graphics library</a></li>
                    <li><a href="http://extjs.com/">ExtJS library</a></li>
                    <li><a href="http://www.cisco.com/web/about/ac50/ac47/2.html">Cisco network diagram icons</a></li>
                </ul>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="container-fluid parent">
    <div class="row parent">
        <div class="col-md-2" id="icons_div"></div>
        <div class="col-md-8" id="paint_div">
            <div id="paintarea" style="position:relative;width:3000px;height:3000px;">
            </div>
        </div>
        <div class="col-md-2" id="results_div">
            <h2>JSON</h2>
            <textarea id='json_text' rows="10" cols="80" style="width: 90%"></textarea>
            <div class="btn-group" role="group" aria-label="...">
                <button type="button" class="btn btn-default" onclick="doLoadJSON();">Load</button>
                <button type="button" class="btn btn-default" onclick="doSaveJSON();">Save</button>
                <button type="button" class="btn btn-default" onclick="doSendJSON();">Analyze</button>
            </div>
            <hr size="1" noshade="noshade"/>
            <h2>NS2</h2>
            <textarea id='ns2_text' rows="10" cols="80" style="width: 90%" readonly="readonly"></textarea>
            <hr size="1" noshade="noshade"/>
            <h2>Log</h2>
            <textarea id='log_text' rows="10" cols="80" style="width: 90%" readonly="readonly"></textarea>
        </div>
    </div>
</div>
<script type="text/javascript">
    /*<![CDATA[*/
    /**********************************************************************************
     *
     * Do the Draw2D Stuff
     *
     **********************************************************************************/
    var workflow = new Workflow("paintarea");

    jQuery(document).ready(function ($) {
        workflow.scrollArea = document.getElementById("paint_div");

        //addLibraryIcon('a100baset_hub');
        addLibraryIcon('asa', 'Physical Node');
        addLibraryIcon('cloud_filled', 'Internet');
        addLibraryIcon('laptop', 'Kali');
        addLibraryIcon('layer_3_switch', 'Windows 7');
        addLibraryIcon('router', 'Router');
        addLibraryIcon('web_server', 'Windows 10');
        addLibraryIcon('workstation', 'Ubuntu 16');

        // TEMPORARY SOLUTION: Hardcoded number of interfaces for each icon
        // TODO: dynamically fetch a XML file from server that specifies the icon details
        var NUM_OF_PORTS = {
            'asa' : 3,
            'cloud_filled' : 4,
            'laptop' : 8,
            'layer_3_switch' : 8,
            'router' : 8,
            'web_server' : 8,
            'workstation' : 8,
        };

        var droptarget = new Ext.dd.DropTarget("paint_div", {ddGroup: 'TreeDD'});
        droptarget.notifyDrop = function (dd, e, data) {<commit_msg>Set correct hardcoded number of interfaces<commit_after><!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>National Cybersecurity Laboratories - Network Topology Tool</title>

    <link rel="shortcut icon" href="images/ncl_favicon1.png" th:href="@{~/images/ncl_favicon1.png}"/>
    <link rel="stylesheet" type="text/css" th:href="@{~/css/bootstrap.min.css}" media="screen"/>
    <link rel="stylesheet" type="text/css" th:href="@{~/css/font-awesome/css/font-awesome.min.css}"/>

    <style>
        html, body {
            height: 100%;
        }
        body {
            overflow: hidden;
        }
        .parent {
            height: 95%;
        }
        #icons_div, #results_div {
            height: 100%;
            overflow-y: scroll;
        }
        #paint_div {
            height: 100%;
            overflow: scroll;
        }
        #paintarea:focus {
            outline: none;
        }
        #ns2_text, #log_text {
            white-space: pre;
            overflow: scroll;
        }
    </style>

    <!-- common, all times required, imports -->
    <script th:src="@{~/topology-tool/wz_jsgraphics.js}"></script>
    <script th:src="@{~/topology-tool/draw2d.js}"></script>

    <!-- demo specific imports -->
    <script th:src="@{~/topology-tool/ResizeImage.js}"></script>
    <script th:src="@{~/topology-tool/ContextmenuConnection.js}"></script>
    <script th:src="@{~/topology-tool/MyInputPort.js}"></script>
    <script th:src="@{~/topology-tool/MyOutputPort.js}"></script>
    <script th:src="@{~/topology-tool/JSONSerializer.js}"></script>
    <script th:src="@{~/topology-tool/DiagramFigure.js}"></script>
    <script th:src="@{~/topology-tool/dom-to-image.min.js}"></script>

    <script type="text/javascript" th:src="@{~/topology-tool/adapter/prototype/prototype.js}"></script>
    <script type="text/javascript" th:src="@{~/js/jquery.min.js}"></script>
    <script type="text/javascript" th:src="@{~/js/bootstrap.min.js}"></script>

    <!--
    References:
    [1] http://learn.jquery.com/using-jquery-core/avoid-conflicts-other-libraries/
    [2] https://www.contrid.co.za/2015/06/fix-bootstrap-3-and-prototype-js-conflict/
    -->
    <script type="text/javascript">
        /*<![CDATA[*/
        var $j = jQuery.noConflict();
        if (Prototype.BrowserFeatures.ElementExtensions) {
            var disablePrototypeJS = function (method, pluginsToDisable) {
                    var handler = function (event) {
                        event.target[method] = undefined;
                        setTimeout(function () {
                            delete event.target[method];
                        }, 0);
                    };
                    pluginsToDisable.each(function (plugin) {
                        jQuery(window).on(method + '.bs.' + plugin, handler);
                    });
                },
                pluginsToDisable = ['collapse', 'dropdown', 'modal', 'tooltip', 'popover', 'tab'];
            disablePrototypeJS('show', pluginsToDisable);
            disablePrototypeJS('hide', pluginsToDisable);
        }
        /*]]>*/
    </script>

    <!-- use this imports if you want use the Yahoo utility methods -->
    <script type="text/javascript" th:src="@{~/topology-tool/adapter/yui/yui-utilities.js}"></script>
    <script type="text/javascript" th:src="@{~/topology-tool/adapter/yui/ext-yui-adapter.js}"></script>
    <script type="text/javascript" th:src="@{~/topology-tool/ext-all.js}"></script>

    <script type="text/javascript">
        /*<![CDATA[*/
        function createNewDiv(aID) {
            var txt = document.createElement('P');
            var div = document.createElement('span');
            div.setAttribute('id', aID);
            txt.setAttribute('id', aID + "_txt");
            div.appendChild(txt);
            return div;
        }

        function loadJSONtext(aText) {
            new JSONSerializer().fromJSON(Ext.util.JSON.decode(aText));
        }

        function addDragIconPic(aName, aWhere, aPic, aDisplay) {
            if (document.getElementById("cont_" + aName)) {
                return;
            }
            var div = document.getElementById(aWhere);
            var cdiv = createNewDiv("cont_" + aName);
            var html = '';
            html = html + "<center>";
            html = html + "<h1>" + aDisplay + "</h1>\n";
            html = html + "<img src='" + aPic + "' id='drag_" + aName + "' style='cursor:move'/>\n";
            html = html + "<hr size=1 noshade>\n";
            html = html + "</center>";

            cdiv.innerHTML = html;
            div.appendChild(cdiv);
            var dragsource = new Ext.dd.DragSource('drag_' + aName, {
                ddGroup: 'TreeDD',
                dragData: {name: 'DiagramFigure', type: aName, pic: aPic}
            });
        }

        function addDragIcon2(aName, aWhere, aDisplay) {
            var aPic = "/topology-tool/icons/" + aName + ".png";
            addDragIconPic(aName, aWhere, aPic, aDisplay);
        }

        function addLibraryIcon(aName, aDisplay) {
            if(aDisplay == undefined) aDisplay = aName;
            addDragIcon2(aName, "icons_div", aDisplay);
        }

        function createNewIconDiv(aID) {
            var txt = document.createElement('P');
            var div = document.createElement('span');
            div.setAttribute('id', aID);
            txt.setAttribute('id', aID + "_txt");
            div.appendChild(txt);
            document.getElementById("icons_div").appendChild(div);
            return div;
        }

        function doSendJSON() {
            var str = $j.trim($j('#json_text').val());
            if (!str) {
                alert("Please save topology to json before analysing.");
            } else {
                $j('#ns2_text').val("");
                $j('#log_text').val("");
                $j.post("/networkTool", { jsonText: str.replace("json_diagram = ", "") })
                    .done(function(data) {
                        var jsonData = $j.parseJSON(data);
                        $j('#ns2_text').val(jsonData.nsText.replace(/&#010;/g, "\n"));
                        $j('#log_text').val(jsonData.logText.replace(/&#010;/g, "\n"));
                    })
                    .fail(function(error) { debug(error); });
            }
        }

        function doSaveJSON() {
            var txt = Ext.util.JSON.encode(new JSONSerializer().toJSON(workflow.getDocument()));
            txt = txt.replace(/,"/g, ', "');
            document.getElementById('json_text').value = txt + "\n\n\n\n";
        }

        function doLoadJSON() {
            document.getElementById('paintarea').innerHTML = "";
            workflow = new Workflow('paintarea');
            workflow.scrollArea = document.getElementById("paint_div");
            loadJSONtext(document.getElementById('json_text').value);
        }

        // To enable function click() in Firefox
        HTMLElement.prototype.click = function() {
            var evt = this.ownerDocument.createEvent('MouseEvents');
            evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
            this.dispatchEvent(evt);
        }

        function doExportDiagramToImage() {
            var BORDERSIZE = 20;
            var $nodes = jQuery('#paintarea').children();

            if ($nodes.length <= 0) {
                alert("There is no diagram to export.");
                return;
            }

            // Find offset and bounds
            var left = Infinity;
            var top = Infinity;
            var right = 0;
            var bottom = 0;
            $nodes.each(function(index, node) {
                var $node = jQuery(node);
                var zIndex = $node.css('zIndex');
                // Calculate bounds for all nodes except line groups
                if (zIndex != '20') {
                    var pos = $node.position();
                    var posRight = pos.left + $node[0].scrollWidth;
                    var posBottom = pos.top + $node[0].scrollHeight;
                    left = (pos.left < left) ? pos.left : left;
                    top = (pos.top < top) ? pos.top : top;
                    right = (posRight > right) ? posRight : right;
                    bottom = (posBottom > bottom) ? posBottom : bottom;
                }
            });

            // Offset all nodes to origin
            $nodes.each(function(index, node) {
                var $node = jQuery(node);
                var pos = $node.position();
                $node.css({ left: pos.left - left + BORDERSIZE, top: pos.top - top + BORDERSIZE });
            });

            domtoimage.toJpeg(document.getElementById('paintarea'), { 
                    filter: function(node) {
                        // Exclude link anchor points
                        return (node.tagName !== 'DIV' || 
                                    (jQuery(node).css('zIndex') != '5000' && 
                                    jQuery(node).css('zIndex') != '10000'));
                    },
                    width: (right - left + BORDERSIZE*2) * window.devicePixelRatio,
                    height: (bottom - top + BORDERSIZE*2) * window.devicePixelRatio,
                    bgcolor: 'white',
                })
                .then(function(dataUrl) {
                    // Download as image
                    var link = document.createElement('a');
                    link.download = 'network-diagram.jpg';
                    link.href = dataUrl;
                    link.click();
                })
                .catch(function(error) {
                    console.error('Oops, something went wrong!', error);
                })
                .finally(function() {
                    // Revert the offset from origin
                    $nodes.each(function(index, node) {
                        var $node = jQuery(node);
                        var pos = $node.position();
                        $node.css({ left: pos.left + left - BORDERSIZE, top: pos.top + top - BORDERSIZE });
                    });
                });
        }

        function debug(message) {
            console.log(message);
        }
        /*]]>*/
    </script>
</head>
<body class="mybg loginbackground">
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" th:href="@{/}"><img src="/images/ncl_favicon1.png" alt="logo" width="20" class="logo1" /></a>
        </div>
        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <!--li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">File <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#"><i class="fa fa-file-text-o"></i> Open</a></li>
                        <li><a href="#"><i class="fa fa-floppy-o"></i> Save</a></li>
                    </ul>
                </li-->
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Library <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Physical Node</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Internet</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Kali</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Windows 7</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Router</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Windows 10</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:visible"></i> Ubuntu 16</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Template <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#"><i class="fa fa-check" style="visibility:hidden"></i> 2 nodes</a></li>
                        <li><a href="#"><i class="fa fa-check" style="visibility:hidden"></i> 3 nodes</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">JSON <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#" onclick="doLoadJSON();"><i class="fa fa-upload"></i> Load</a></li>
                        <li><a href="#" onclick="doSaveJSON();"><i class="fa fa-download"></i> Save</a></li>
                        <li><a href="#" onclick="doSendJSON();"><i class="fa fa-cloud-upload"></i> Analyze</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Export <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#" onclick="doExportDiagramToImage();"><i class="fa fa-file-image-o"></i> Diagram As Image (.JPG)</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Help <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#" data-toggle="modal" data-target="#helpModal"><i class="fa fa-question"></i> Help</a></li>
                        <li><a href="#" data-toggle="modal" data-target="#aboutModal"><i class="fa fa-info"></i> About</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>
<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel" id="helpModal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">How to use</h4>
            </div>
            <div class="modal-body">
                <ul>
                    <li>Drag and drop. Connect the blue dots with lines. Double-click to add the annotations.</li>
                    <li>Control-drag the blue dots to clone them. Click on the unchecked links in the "Library" to add icons.</li>
                    <li>"Save" JSON into the textbox. "Load" JSON from the textbox. "Analyze" JSON to get the NS file and other associated files.</li>
                </ul>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="aboutModalLabel" id="aboutModal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">About</h4>
            </div>
            <div class="modal-body">
                <p>
                    This little hack is standing on the shoulders of giants:
                </p>
                <ul>
                    <li><a href="http://draw2d.org/">Draw2D library</a></li>
                    <li><a href="http://www.walterzorn.com/">Walter Zorn's JS graphics library</a></li>
                    <li><a href="http://extjs.com/">ExtJS library</a></li>
                    <li><a href="http://www.cisco.com/web/about/ac50/ac47/2.html">Cisco network diagram icons</a></li>
                </ul>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="container-fluid parent">
    <div class="row parent">
        <div class="col-md-2" id="icons_div"></div>
        <div class="col-md-8" id="paint_div">
            <div id="paintarea" style="position:relative;width:3000px;height:3000px;">
            </div>
        </div>
        <div class="col-md-2" id="results_div">
            <h2>JSON</h2>
            <textarea id='json_text' rows="10" cols="80" style="width: 90%"></textarea>
            <div class="btn-group" role="group" aria-label="...">
                <button type="button" class="btn btn-default" onclick="doLoadJSON();">Load</button>
                <button type="button" class="btn btn-default" onclick="doSaveJSON();">Save</button>
                <button type="button" class="btn btn-default" onclick="doSendJSON();">Analyze</button>
            </div>
            <hr size="1" noshade="noshade"/>
            <h2>NS2</h2>
            <textarea id='ns2_text' rows="10" cols="80" style="width: 90%" readonly="readonly"></textarea>
            <hr size="1" noshade="noshade"/>
            <h2>Log</h2>
            <textarea id='log_text' rows="10" cols="80" style="width: 90%" readonly="readonly"></textarea>
        </div>
    </div>
</div>
<script type="text/javascript">
    /*<![CDATA[*/
    /**********************************************************************************
     *
     * Do the Draw2D Stuff
     *
     **********************************************************************************/
    var workflow = new Workflow("paintarea");

    jQuery(document).ready(function ($) {
        workflow.scrollArea = document.getElementById("paint_div");

        //addLibraryIcon('a100baset_hub');
        addLibraryIcon('asa', 'Physical Node');
        addLibraryIcon('cloud_filled', 'Internet');
        addLibraryIcon('laptop', 'Kali');
        addLibraryIcon('layer_3_switch', 'Windows 7');
        addLibraryIcon('router', 'Router');
        addLibraryIcon('web_server', 'Windows 10');
        addLibraryIcon('workstation', 'Ubuntu 16');

        // TEMPORARY SOLUTION: Hardcoded number of interfaces for each icon
        // TODO: dynamically fetch a XML file from server that specifies the icon details
        var NUM_OF_PORTS = {
            'asa' : 3,
            'cloud_filled' : 1,
            'laptop' : 8,
            'layer_3_switch' : 8,
            'router' : 8,
            'web_server' : 8,
            'workstation' : 8,
        };

        var droptarget = new Ext.dd.DropTarget("paint_div", {ddGroup: 'TreeDD'});
        droptarget.notifyDrop = function (dd, e, data) {
{'fraction_non_alphanumeric': 0.17697505836097802, 'fraction_numerical': 0.007814227792112053, 'mean_word_length': 1.8679351656095842, 'pattern_counts': {'":': 0, '<': 703, '<?xml version=': 0, '>': 699, 'https://': 2, 'lorem ipsum': 0, 'www.': 10, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5101273', 'n_tokens_mistral': 11933, 'n_tokens_neox': 11210, 'n_words': 2275}