lanscape 1.2.6a10__py3-none-any.whl → 1.2.6a12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. lanscape/ui/static/css/style.css +715 -0
  2. lanscape/ui/static/img/ico/android-chrome-192x192.png +0 -0
  3. lanscape/ui/static/img/ico/android-chrome-512x512.png +0 -0
  4. lanscape/ui/static/img/ico/apple-touch-icon.png +0 -0
  5. lanscape/ui/static/img/ico/favicon-16x16.png +0 -0
  6. lanscape/ui/static/img/ico/favicon-32x32.png +0 -0
  7. lanscape/ui/static/img/ico/favicon.ico +0 -0
  8. lanscape/ui/static/img/ico/site.webmanifest +1 -0
  9. lanscape/ui/static/img/readme1.png +0 -0
  10. lanscape/ui/static/js/core.js +39 -0
  11. lanscape/ui/static/js/layout-sizing.js +31 -0
  12. lanscape/ui/static/js/main.js +208 -0
  13. lanscape/ui/static/js/quietReload.js +23 -0
  14. lanscape/ui/static/js/shutdown-server.js +17 -0
  15. lanscape/ui/static/js/subnet-info.js +19 -0
  16. lanscape/ui/static/js/subnet-selector.js +9 -0
  17. lanscape/ui/static/lanscape.webmanifest +19 -0
  18. lanscape/ui/templates/base.html +47 -0
  19. lanscape/ui/templates/core/head.html +10 -0
  20. lanscape/ui/templates/core/scripts.html +5 -0
  21. lanscape/ui/templates/error.html +35 -0
  22. lanscape/ui/templates/info.html +67 -0
  23. lanscape/ui/templates/main.html +89 -0
  24. lanscape/ui/templates/scan/export.html +27 -0
  25. lanscape/ui/templates/scan/ip-table-row.html +103 -0
  26. lanscape/ui/templates/scan/ip-table.html +26 -0
  27. lanscape/ui/templates/scan/overview.html +28 -0
  28. lanscape/ui/templates/scan/scan-error.html +33 -0
  29. lanscape/ui/templates/scan.html +14 -0
  30. lanscape/ui/templates/shutdown.html +23 -0
  31. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/METADATA +1 -1
  32. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/RECORD +35 -5
  33. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/LICENSE +0 -0
  34. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/WHEEL +0 -0
  35. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,39 @@
1
+ $(document).ready(function() {
2
+ rightSizeDocLayout(0,showFooter);
3
+ initTooltips();
4
+ })
5
+
6
+ $(window).on('resize', function() {
7
+ rightSizeDocLayout();
8
+ });
9
+
10
+
11
+ function rightSizeDocLayout(delay=20,callback=null) {
12
+ setTimeout(() => {
13
+ const content = $('#content');
14
+ if (content) {
15
+ const headerHeight = $('#header').outerHeight();
16
+ const footerHeight = $('footer').outerHeight();
17
+ const viewportHeight = $(window).height();
18
+
19
+ const newHeight = viewportHeight - headerHeight - footerHeight;
20
+ content.height(newHeight);
21
+
22
+ }
23
+ if (callback) callback();
24
+ },delay);
25
+ }
26
+
27
+ function showFooter() {
28
+ const footer = $('footer');
29
+ footer.removeClass('div-hide');
30
+ setTimeout(() => {footer.css('transform','translateY(0px)')},1);
31
+ }
32
+
33
+
34
+ function initTooltips() {
35
+ var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
36
+ tooltipTriggerList.map(function (tooltipTriggerEl) {
37
+ return new bootstrap.Tooltip(tooltipTriggerEl)
38
+ })
39
+ }
@@ -0,0 +1,31 @@
1
+ $(document).ready(function() {
2
+ rightSizeDocLayout(0,showFooter);
3
+ })
4
+
5
+ $(window).on('resize', function() {
6
+ rightSizeDocLayout();
7
+ });
8
+
9
+
10
+ function rightSizeDocLayout(delay=20,callback=null) {
11
+ setTimeout(() => {
12
+ const content = $('#content');
13
+ if (content) {
14
+ const headerHeight = $('#header').outerHeight();
15
+ const footerHeight = $('footer').outerHeight();
16
+ const viewportHeight = $(window).height();
17
+
18
+ const newHeight = viewportHeight - headerHeight - footerHeight;
19
+ content.height(newHeight);
20
+
21
+ }
22
+ if (callback) callback();
23
+ },delay);
24
+ }
25
+
26
+ function showFooter() {
27
+ const footer = $('footer');
28
+ footer.removeClass('div-hide');
29
+ setTimeout(() => {footer.css('transform','translateY(0px)')},1);
30
+ }
31
+
@@ -0,0 +1,208 @@
1
+
2
+
3
+ $(document).ready(function() {
4
+ // Load port lists into the dropdown
5
+ getPortLists();
6
+
7
+ $('#parallelism').on('input', function() {
8
+ const val = $('#parallelism').val();
9
+ let ans = val;
10
+
11
+ if (parseFloat(val) > 1) {
12
+ ans += ' <span>Warning: Increased parallelism may have inaccurate results<span>'
13
+ }
14
+ $('#parallelism-value').html(ans);
15
+ });
16
+ const scanId = getActiveScanId();
17
+ if (scanId) {
18
+ showScan(scanId);
19
+ }
20
+
21
+
22
+ // Handle form submission
23
+ $('#scan-form').on('submit', function(event) {
24
+ event.preventDefault();
25
+ if ($('#scan-submit').text() == 'Scan') {
26
+ submitNewScan()
27
+ } else {
28
+ terminateScan();
29
+ }
30
+
31
+
32
+ });
33
+
34
+ // Handle filter input
35
+ $('#filter').on('input', function() {
36
+ const filter = $(this).val();
37
+ const currentSrc = $('#ip-table-frame').attr('src');
38
+ const newSrc = currentSrc.split('?')[0] + '?filter=' + filter;
39
+ $('#ip-table-frame').attr('src', newSrc);
40
+ });
41
+
42
+ });
43
+
44
+ function submitNewScan() {
45
+ const formData = {
46
+ subnet: $('#subnet').val(),
47
+ port_list: $('#port-list').text(),
48
+ parallelism: $('#parallelism').val()
49
+ };
50
+ $.ajax('/api/scan', {
51
+ data : JSON.stringify(formData),
52
+ contentType : 'application/json',
53
+ type : 'POST',
54
+ success: function(response) {
55
+ if (response.status === 'running') {
56
+ showScan(response.scan_id);
57
+ }
58
+ }
59
+ });
60
+ }
61
+
62
+ function getActiveScanId() {
63
+ const url = new URL(window.location.href);
64
+ return url.searchParams.get('scan_id');
65
+ }
66
+
67
+ function showScan(scanId) {
68
+ pollScanSummary(scanId);
69
+ setScanState(false);
70
+
71
+ $('#no-scan').addClass('div-hide');
72
+ $('#scan-results').removeClass('div-hide');
73
+
74
+ $('#export-link').attr('href','/export/' + scanId);
75
+ //$('#overview-frame').attr('src', '/scan/' + scanId + '/overview');
76
+ $('#ip-table-frame').attr('src', '/scan/' + scanId + '/table');
77
+
78
+ // set url query string 'scan_id' to the scan_id
79
+ const url = new URL(window.location.href);
80
+ url.searchParams.set('scan_id', scanId);
81
+ // set url to the new url
82
+ window.history.pushState({}, '', url);
83
+ }
84
+
85
+ function getPortLists() {
86
+ $.get('/api/port/list', function(data) {
87
+ const customSelect = $('#port-list');
88
+ const customSelectDropdown = $('#port-list-dropdown');
89
+ customSelectDropdown.empty();
90
+
91
+ // Populate the dropdown with the options
92
+ data.forEach(function(portList) {
93
+ customSelectDropdown.append('<div>' + portList + '</div>');
94
+ });
95
+
96
+ // Handle dropdown click
97
+ customSelect.on('click', function() {
98
+ customSelectDropdown.toggleClass('open');
99
+ });
100
+
101
+ // Handle option selection
102
+ customSelectDropdown.on('click', 'div', function() {
103
+ const selectedOption = $(this).text();
104
+ customSelect.text(selectedOption);
105
+ customSelectDropdown.removeClass('open');
106
+ });
107
+ });
108
+ }
109
+
110
+ $(document).on('click', function(event) {
111
+ if (!$(event.target).closest('.port-list-wrapper').length) {
112
+ $('#port-list-dropdown').removeClass('open');
113
+ }
114
+ });
115
+
116
+ function setScanState(scanEnabled) {
117
+ const button = $('#scan-submit');
118
+ console.log('set scan state- scanning',scanEnabled)
119
+
120
+ if (scanEnabled) {
121
+ button.text("Scan");
122
+ button.removeClass('btn-danger').addClass('btn-primary');
123
+ } else {
124
+ button.text("Stop");
125
+ button.removeClass('btn-primary').addClass('btn-danger');
126
+ }
127
+ }
128
+
129
+
130
+ function resizeIframe(iframe) {
131
+ // Adjust the height of the iframe to match the content
132
+ setTimeout( () => {
133
+ iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 'px';
134
+ },100);
135
+ }
136
+
137
+ function observeIframeContent(iframe) {
138
+ const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
139
+
140
+ // Use MutationObserver to observe changes within the iframe
141
+ const observer = new MutationObserver(() => {
142
+ resizeIframe(iframe);
143
+ });
144
+
145
+ // Configure the observer to watch for changes in the subtree of the body
146
+ observer.observe(iframeDocument.body, {
147
+ childList: true,
148
+ subtree: true,
149
+ attributes: true, // In case styles/attributes change height
150
+ });
151
+ }
152
+ function terminateScan() {
153
+ const button = $('#scan-submit');
154
+ button.prop('disabled', true);
155
+ const scanId = getActiveScanId();
156
+ $.get(`/api/scan/${scanId}/terminate`, function(ans) {
157
+ setScanState(true);
158
+ button.prop('disabled', false);
159
+ });
160
+ }
161
+ function pollScanSummary(id) {
162
+ $.get(`/api/scan/${id}/summary`, function(summary) {
163
+ let progress = $('#scan-progress-bar');
164
+ if (summary.running || summary.stage == 'terminating') {
165
+ progress.css('height','2px');
166
+ progress.css('width',`${summary.percent_complete}vw`);
167
+ // TODO: move overview here??
168
+ setTimeout(() => {pollScanSummary(id)},500);
169
+ } else {
170
+ progress.css('width','100vw');
171
+ progress.css('background-color','var(--success-accent)')
172
+ setTimeout(() => {progress.css('height','0px');},500);
173
+ setScanState(true);
174
+
175
+ // wait to make the width smaller for animation to be clean
176
+ setTimeout(() => {
177
+ progress.css('width','0vw');
178
+ progress.css('background-color','var(--primary-accent)')
179
+ },1000);
180
+ }
181
+ updateOverviewUI(summary);
182
+ });
183
+ }
184
+
185
+ function updateOverviewUI(summary) {
186
+ $('#scan-devices-alive').text(summary.devices.alive);
187
+ $('#scan-devices-scanned').text(summary.devices.scanned);
188
+ $('#scan-devices-total').text(summary.devices.total);
189
+ $('#scan-run-time').text(summary.runtime);
190
+ $('#scan-stage').text(summary.stage);
191
+ }
192
+
193
+ // Bind the iframe's load event to initialize the observer
194
+ $('#ip-table-frame').on('load', function() {
195
+ resizeIframe(this); // Initial resizing after iframe loads
196
+ observeIframeContent(this); // Start observing for dynamic changes
197
+ });
198
+
199
+
200
+
201
+ $(window).on('resize', function() {
202
+ resizeIframe($('#ip-table-frame')[0]);
203
+ });
204
+
205
+
206
+
207
+
208
+
@@ -0,0 +1,23 @@
1
+ // Reload the page gracefully every second
2
+ // Used in 'live' iframes
3
+
4
+ function quietReload() {
5
+ function run() {
6
+ $.get(document.location.href, function(data) {
7
+ // create a new document from the fetched data
8
+ var newDoc = new DOMParser().parseFromString(data, 'text/html');
9
+ // replace current body with the new body content
10
+ $('body').html($(newDoc.body).html());
11
+ });
12
+ }
13
+ setTimeout(function() {
14
+ // get current page via ajax, and replace the current page with the new one
15
+ try {
16
+ run();
17
+ } catch (e) {
18
+ console.error(e);
19
+ quietReload();
20
+ }
21
+ }, 1000);
22
+ }
23
+ quietReload();
@@ -0,0 +1,17 @@
1
+ $(document).ready(function() {
2
+ setTimeout(() => shutdownApp(), 2000);
3
+ });
4
+
5
+
6
+
7
+ function shutdownApp() {
8
+ // will term server before response
9
+ $.get('/shutdown').always(() => serverDown());
10
+ }
11
+
12
+ function serverDown() {
13
+ $('#shutdown-message').html('Server down.');
14
+ $('#shutdown-sub').html('You can close this browser window.');
15
+ $('#shutdown-sub-sub').html('(since your browser wont let me)');
16
+ setTimeout(() => window.close(),2500);
17
+ }
@@ -0,0 +1,19 @@
1
+ // Validation for subnet input
2
+
3
+ $(document).ready(function() {
4
+ $('#subnet').on('input', () => subnetUpdated($('#subnet').val()));
5
+ subnetUpdated($('#subnet').val());
6
+ });
7
+
8
+ function subnetUpdated(input) {
9
+ $.getJSON(`/api/tools/subnet/test?subnet=${input}`,(data) => {
10
+ setSubnetValidity(data.valid);
11
+ $('#subnet-info').html(data.msg);
12
+ })
13
+ }
14
+
15
+ function setSubnetValidity(valid) { //boolean
16
+ if (valid) $('#scan-form').removeClass('error');
17
+ else $('#scan-form').addClass('error');
18
+ $("#scan-submit").attr("disabled",!valid);
19
+ }
@@ -0,0 +1,9 @@
1
+ $(document).ready(function () {
2
+ // Update input box when selecting a dropdown item
3
+ $('.dropdown-item').on('click', function (e) {
4
+ e.preventDefault();
5
+ let selectedSubnet = $(this).text();
6
+ $('#subnet').val(selectedSubnet); // Update input with selection
7
+ subnetUpdated(selectedSubnet); // from subnet-info.js
8
+ });
9
+ });
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "LANscape",
3
+ "short_name": "LANscape",
4
+ "icons": [
5
+ {
6
+ "src": "/static/img/ico/android-chrome-192x192.png",
7
+ "sizes": "192x192",
8
+ "type": "image/png"
9
+ },
10
+ {
11
+ "src": "/static/img/ico/android-chrome-512x512.png",
12
+ "sizes": "512x512",
13
+ "type": "image/png"
14
+ }
15
+ ],
16
+ "theme_color": "#0856a9",
17
+ "background_color": "#1e1e1e",
18
+ "display": "standalone"
19
+ }
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ {% include 'core/head.html' %}
5
+ {% include 'core/scripts.html' %}
6
+ </head>
7
+ <body>
8
+
9
+ {% block content %}{% endblock %}
10
+ <footer class="div-hide">
11
+ <div class="version">
12
+ v{{app_version}}
13
+ {% if is_local %}
14
+ <span>(Local Run)</span>
15
+ {% elif update_available %}
16
+ <span>(Update Available)</span>
17
+ {% endif %}
18
+ </div>
19
+
20
+ <div id="app-actions">
21
+ <a href="/info">
22
+ <span
23
+ class="material-symbols-outlined"
24
+ data-bs-toggle="tooltip"
25
+ data-bs-placement="top"
26
+ title="App info">
27
+ info
28
+ </span>
29
+ </a>
30
+
31
+ {% if runtime_args.get('nogui') or runtime_args.get('headless') %}
32
+ <a href="/shutdown-ui">
33
+ <span
34
+ id="power-button"
35
+ class="material-symbols-outlined"
36
+ data-bs-toggle="tooltip"
37
+ data-bs-placement="top"
38
+ title="Shutdown App">
39
+ power_settings_new
40
+ </span>
41
+ </a>
42
+ {% endif %}
43
+ </div>
44
+
45
+ </footer>
46
+ </body>
47
+ </html>
@@ -0,0 +1,10 @@
1
+ <meta charset="UTF-8">
2
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
3
+ <title>LANscape</title>
4
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
5
+ <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
6
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
7
+ <link rel="apple-touch-icon" sizes="180x180" href="/static/img/ico/apple-touch-icon.png">
8
+ <link rel="icon" type="image/png" sizes="32x32" href="/static/img/ico/favicon-32x32.png">
9
+ <link rel="icon" type="image/png" sizes="16x16" href="/static/img/ico/favicon-16x16.png">
10
+ <link rel="manifest" href="/static/lanscape.webmanifest">
@@ -0,0 +1,5 @@
1
+ <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
2
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
3
+ <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
4
+ <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
5
+ <script src="{{ url_for('static', filename='js/core.js') }}"></script>
@@ -0,0 +1,35 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div id="header">
5
+ <!-- Header and Scan Submission Inline -->
6
+ <div class="d-flex justify-content-start align-items-center">
7
+ <h1 class="title" onclick="location.href = '/'">
8
+ <span>LAN</span>scape
9
+ </h1>
10
+ </div>
11
+ </div>
12
+ <div class="scroll-container" id="content">
13
+ <div class="container-fluid my-4">
14
+ <h3 class="text-danger">500 - Internal Server Error</h3>
15
+ <h5>{{ error or 'That was unexpected.' }}</h5>
16
+
17
+ {% if traceback %}
18
+ <details>
19
+ <summary>Traceback:</summary>
20
+ <div class="error-container">
21
+ <pre>{{traceback}}</pre>
22
+ </div>
23
+ </details>
24
+ {% endif %}
25
+
26
+ <button onclick="location.href='/'" class="btn btn-primary m-2">Home</button>
27
+
28
+ <a href="https://github.com/mdennis281/LANscape/issues" target="_blank">
29
+ <button class="btn btn-info m-2">Github issues</button>
30
+ </a>
31
+ </div>
32
+ </div>
33
+
34
+ {% endblock %}
35
+
@@ -0,0 +1,67 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div id="header">
5
+ <!-- Header and Scan Submission Inline -->
6
+ <div class="d-flex justify-content-start align-items-center">
7
+ <h1 class="title" onclick="location.href = '/'">
8
+ <span>LAN</span>scape
9
+ </h1>
10
+ </div>
11
+ </div>
12
+ <div class="scroll-container" id="content">
13
+ {% if update_available %}
14
+ <div class="container-fluid my-4">
15
+ <h3>New version available!</h3>
16
+ <p>
17
+ A new version has been published to PyPi.
18
+ ({{app_version}} -> {{latest_version}})
19
+ </p>
20
+ <input type="text" readonly class="form-control mb-3 mt-3" value="pip install --upgrade lanscape --no-cache"/>
21
+ <a href="https://pypi.org/project/lanscape/" target="_blank"></a>
22
+ <button class="btn btn-primary m-2">PyPi - Lanscape</button>
23
+ </a>
24
+ </div>
25
+ {% endif %}
26
+ <div class="container-fluid my-4">
27
+ <h3>About</h3>
28
+ <p>
29
+ LANscape was born from my frustration with existing local network scanning tools
30
+ alongside my desire to dive deeper into technologies like
31
+ Address Resolution Protocol (ARP), threadpooling, & Python packaging.
32
+ I set out to create something faster, lightweight, & easier to use.
33
+ This project has been a learning journey, & I hope it helps you
34
+ discover more about your network as well. Enjoy!
35
+ </p>
36
+ <a href="https://github.com/mdennis281/" target="_blank"></a>
37
+ <button class="btn btn-primary m-2">Github</button>
38
+ </a>
39
+ <a href="https://github.com/mdennis281/LANscape" target="_blank">
40
+ <button class="btn btn-secondary m-2">Project Repo</button>
41
+ </a>
42
+ </div>
43
+ <div class="container-fluid my-4">
44
+ <h3>Runtime Arguments</h3>
45
+ <table class="table table-striped table-bordered">
46
+ <thead class="table-dark">
47
+ <tr>
48
+ <th>Key</th>
49
+ <th>Value</th>
50
+ </tr>
51
+ </thead>
52
+ <tbody>
53
+ {% for key, value in runtime_args.items() %}
54
+ <tr>
55
+ <td>{{ key }}</td>
56
+ <td>{{ value }}</td>
57
+ </tr>
58
+ {% endfor %}
59
+ </tbody>
60
+ </table>
61
+ </div>
62
+
63
+
64
+ </div>
65
+
66
+ {% endblock %}
67
+
@@ -0,0 +1,89 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div id="header">
5
+ <!-- Header and Scan Submission Inline -->
6
+ <div class="d-flex justify-content-between align-items-center flex-wrap">
7
+ <h1 class="title" onclick="location.reload()">
8
+ <span>LAN</span>scape
9
+ </h1>
10
+ <!-- Form -->
11
+ <form id="scan-form" class="d-flex align-items-end">
12
+ <div class="form-group me-2">
13
+ <div class="label-container">
14
+ <label for="subnet">Subnet:</label>
15
+ <div id="subnet-info"></div>
16
+ </div>
17
+ <div class="input-group">
18
+ <input type="text" id="subnet" name="subnet" class="form-control" value="{{ subnet }}" placeholder="Enter subnet">
19
+ <button class="btn btn-secondary dropdown-toggle" type="button" id="subnet-dropdown" data-bs-toggle="dropdown" aria-expanded="false"></button>
20
+ <ul class="dropdown-menu" aria-labelledby="subnet-dropdown" id="dropdown-list">
21
+ {% for subnet_option in alternate_subnets %}
22
+ <li><a class="dropdown-item" href="#">{{ subnet_option['subnet'] }}</a></li>
23
+ {% endfor %}
24
+ </ul>
25
+ </div>
26
+ </div>
27
+ <button type="submit" id="scan-submit" class="btn btn-primary mb-3">Scan</button>
28
+ </form>
29
+ </div>
30
+
31
+ <!-- Advanced Section -->
32
+ <details onclick="rightSizeDocLayout()">
33
+ <summary>Advanced</summary>
34
+ <div class="form-group mt-2">
35
+ <label for="port_list">Port List:</label>
36
+ <div class="port-list-wrapper">
37
+ <div id="port-list" class="port-list">{{port_list}}</div>
38
+ <div id="port-list-dropdown" class="port-list-dropdown"></div>
39
+ </div>
40
+ </div>
41
+
42
+ <div class="form-group mt-2">
43
+ <label for="parallelism">Parallelism:</label>
44
+ <input type="range" id="parallelism" name="parallelism" min="0.25" max="3" step="0.05" value="{{parallelism}}">
45
+ <output id="parallelism-value">{{parallelism}}</output>
46
+ </div>
47
+ </details>
48
+ <div id="scan-progress-bar"></div>
49
+ </div>
50
+ <div id="content">
51
+ <div class="container-fluid my-4">
52
+ <!-- Scan Results -->
53
+ <div id="scan-results" class="div-hide">
54
+ <div class="d-flex justify-content-between">
55
+ <h2>Scan Results</h2>
56
+ <div id="scan-actions">
57
+ <a href="" id="export-link">
58
+ <span
59
+ class="material-symbols-outlined secondary-icon-btn"
60
+ data-bs-toggle="tooltip"
61
+ data-bs-placement="top"
62
+ title="Export scan to json">
63
+ ios_share
64
+ </span>
65
+ </a>
66
+ </div>
67
+ </div>
68
+
69
+ {% include 'scan/overview.html' %}
70
+ <input type="text" id="filter" placeholder="Filter results" class="form-control mb-3 mt-3">
71
+ <div class="table-frame-container">
72
+ <iframe id="ip-table-frame" src=""></iframe>
73
+ </div>
74
+ </div>
75
+ <div id="no-scan">
76
+ <h2>No results to show</h2>
77
+ <p>Submit a scan above</p>
78
+ </div>
79
+ </div>
80
+ </div>
81
+
82
+
83
+ <script src="{{ url_for('static', filename='js/main.js') }}"></script>
84
+ <script src="{{ url_for('static', filename='js/subnet-info.js') }}"></script>
85
+ <script src="{{ url_for('static', filename='js/subnet-selector.js') }}"></script>
86
+ {% endblock %}
87
+
88
+
89
+
@@ -0,0 +1,27 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div id="header">
5
+ <!-- Header and Scan Submission Inline -->
6
+ <div class="d-flex justify-content-start align-items-center">
7
+ <h1 class="title" onclick="location.href = '/'">
8
+ <span>LAN</span>scape
9
+ </h1>
10
+ </div>
11
+ </div>
12
+ <div class="scroll-container" id="#content">
13
+ <div class="container-fluid my-4">
14
+ <h3>Json Export:</h3>
15
+
16
+ <details>
17
+ <summary>{{ scan.uid }}</summary>
18
+ <div class="error-container">
19
+ <pre>{{ export_json }}</pre>
20
+ </div>
21
+ </details>
22
+ <button onclick="location.href='/?scan_id={{scan.uid}}'" class="btn btn-primary m-2">Back</button>
23
+ </div>
24
+ </div>
25
+
26
+ {% endblock %}
27
+