lanscape 1.3.4__py3-none-any.whl → 1.3.5a2__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 (39) hide show
  1. lanscape/libraries/app_scope.py +0 -1
  2. lanscape/libraries/decorators.py +10 -5
  3. lanscape/libraries/errors.py +10 -0
  4. lanscape/libraries/ip_parser.py +73 -1
  5. lanscape/libraries/logger.py +29 -1
  6. lanscape/libraries/mac_lookup.py +5 -0
  7. lanscape/libraries/net_tools.py +139 -68
  8. lanscape/libraries/port_manager.py +83 -0
  9. lanscape/libraries/runtime_args.py +12 -0
  10. lanscape/libraries/scan_config.py +148 -5
  11. lanscape/libraries/service_scan.py +3 -3
  12. lanscape/libraries/subnet_scan.py +104 -16
  13. lanscape/libraries/version_manager.py +50 -7
  14. lanscape/libraries/web_browser.py +136 -68
  15. lanscape/resources/mac_addresses/convert_csv.py +13 -2
  16. lanscape/resources/ports/convert_csv.py +13 -3
  17. lanscape/ui/__init__.py +0 -0
  18. lanscape/ui/app.py +32 -36
  19. lanscape/ui/blueprints/__init__.py +4 -1
  20. lanscape/ui/blueprints/api/__init__.py +2 -0
  21. lanscape/ui/blueprints/api/port.py +46 -0
  22. lanscape/ui/blueprints/api/scan.py +58 -10
  23. lanscape/ui/blueprints/api/tools.py +17 -1
  24. lanscape/ui/blueprints/web/__init__.py +4 -0
  25. lanscape/ui/blueprints/web/routes.py +52 -5
  26. lanscape/ui/main.py +17 -7
  27. lanscape/ui/shutdown_handler.py +57 -0
  28. lanscape/ui/static/css/style.css +94 -20
  29. lanscape/ui/static/js/main.js +25 -48
  30. lanscape/ui/static/js/scan-config.js +107 -0
  31. lanscape/ui/static/lanscape.webmanifest +4 -3
  32. lanscape/ui/templates/main.html +39 -36
  33. lanscape/ui/templates/scan/config.html +168 -0
  34. {lanscape-1.3.4.dist-info → lanscape-1.3.5a2.dist-info}/METADATA +1 -1
  35. lanscape-1.3.5a2.dist-info/RECORD +73 -0
  36. lanscape-1.3.4.dist-info/RECORD +0 -69
  37. {lanscape-1.3.4.dist-info → lanscape-1.3.5a2.dist-info}/WHEEL +0 -0
  38. {lanscape-1.3.4.dist-info → lanscape-1.3.5a2.dist-info}/licenses/LICENSE +0 -0
  39. {lanscape-1.3.4.dist-info → lanscape-1.3.5a2.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,7 @@
1
+ """
2
+ Web blueprint routes for the LANscape application.
3
+ Handles UI views including the main dashboard, scan results, error display, and exports.
4
+ """
1
5
  from flask import render_template, request, redirect
2
6
  from lanscape.ui.blueprints.web import web_bp
3
7
  from lanscape.libraries.net_tools import (
@@ -12,16 +16,20 @@ from lanscape.ui.blueprints import scan_manager, log
12
16
 
13
17
  @web_bp.route('/', methods=['GET'])
14
18
  def index():
19
+ """
20
+ Render the main application interface.
21
+
22
+ Displays the primary network subnet selection interface and existing scan results.
23
+ If a scan_id is provided, it loads the configuration from that scan.
24
+ """
15
25
  subnets = get_all_network_subnets()
16
26
  subnet = smart_select_primary_subnet(subnets)
17
27
 
18
28
  port_list = 'medium'
19
- parallelism = 1
20
29
  if scan_id := request.args.get('scan_id'):
21
30
  if scan := scan_manager.get_scan(scan_id):
22
31
  subnet = scan.cfg.subnet
23
32
  port_list = scan.cfg.port_list
24
- parallelism = scan.cfg.t_multiplier
25
33
 
26
34
  else:
27
35
  log.debug(f'Redirecting, scan {scan_id} doesnt exist in memory')
@@ -30,7 +38,6 @@ def index():
30
38
  'main.html',
31
39
  subnet=subnet,
32
40
  port_list=port_list,
33
- parallelism=parallelism,
34
41
  alternate_subnets=subnets
35
42
  )
36
43
 
@@ -38,16 +45,35 @@ def index():
38
45
  @web_bp.route('/scan/<scan_id>', methods=['GET'])
39
46
  @web_bp.route('/scan/<scan_id>/<section>', methods=['GET'])
40
47
  def render_scan(scan_id, section='all'):
48
+ """
49
+ Render a specific scan result.
50
+
51
+ Args:
52
+ scan_id: Unique identifier for the scan
53
+ section: Section of the scan results to display (default: 'all')
54
+
55
+ Returns:
56
+ Rendered scan template or redirect to home if scan not found
57
+ """
41
58
  if scanner := scan_manager.get_scan(scan_id):
42
59
  data = scanner.results.export()
43
- filter = request.args.get('filter')
44
- return render_template('scan.html', data=data, section=section, filter=filter)
60
+ filter_text = request.args.get('filter')
61
+ return render_template('scan.html', data=data, section=section, filter=filter_text)
45
62
  log.debug(f'Redirecting, scan {scan_id} doesnt exist in memory')
46
63
  return redirect('/')
47
64
 
48
65
 
49
66
  @web_bp.route('/errors/<scan_id>')
50
67
  def view_errors(scan_id):
68
+ """
69
+ Display errors that occurred during a scan.
70
+
71
+ Args:
72
+ scan_id: Unique identifier for the scan
73
+
74
+ Returns:
75
+ Rendered error template or redirect to home if scan not found
76
+ """
51
77
  if scanner := scan_manager.get_scan(scan_id):
52
78
  data = scanner.results.export()
53
79
  return render_template('scan/scan-error.html', data=data)
@@ -57,6 +83,15 @@ def view_errors(scan_id):
57
83
 
58
84
  @web_bp.route('/export/<scan_id>')
59
85
  def export_scan(scan_id):
86
+ """
87
+ Provide an exportable view of scan results.
88
+
89
+ Args:
90
+ scan_id: Unique identifier for the scan
91
+
92
+ Returns:
93
+ Rendered export template or redirect to home if scan not found
94
+ """
60
95
  if scanner := scan_manager.get_scan(scan_id):
61
96
  export_json = scanner.results.export(str)
62
97
  return render_template(
@@ -70,9 +105,21 @@ def export_scan(scan_id):
70
105
 
71
106
  @web_bp.route('/shutdown-ui')
72
107
  def shutdown_ui():
108
+ """
109
+ Display the shutdown confirmation page.
110
+
111
+ Returns:
112
+ Rendered shutdown template
113
+ """
73
114
  return render_template('shutdown.html')
74
115
 
75
116
 
76
117
  @web_bp.route('/info')
77
118
  def app_info():
119
+ """
120
+ Display application information and version details.
121
+
122
+ Returns:
123
+ Rendered info template
124
+ """
78
125
  return render_template('info.html')
lanscape/ui/main.py CHANGED
@@ -1,4 +1,4 @@
1
-
1
+ """Main entry point for the LANscape application when running as a module."""
2
2
  import socket
3
3
 
4
4
 
@@ -7,8 +7,10 @@ import time
7
7
  import logging
8
8
  import traceback
9
9
  import os
10
+ import requests
11
+
10
12
  from lanscape.libraries.logger import configure_logging
11
- from lanscape.libraries.runtime_args import parse_args, RuntimeArgs
13
+ from lanscape.libraries.runtime_args import parse_args
12
14
  from lanscape.libraries.web_browser import open_webapp
13
15
  from lanscape.libraries.net_tools import is_arp_supported
14
16
  from lanscape.libraries.version_manager import get_installed_version, is_update_available
@@ -25,6 +27,7 @@ IS_FLASK_RELOAD = os.environ.get("WERKZEUG_RUN_MAIN")
25
27
 
26
28
 
27
29
  def main():
30
+ """core entry point for running lanscape as a module."""
28
31
  try:
29
32
  _main()
30
33
  except KeyboardInterrupt:
@@ -47,10 +50,15 @@ def _main():
47
50
  args.port = get_valid_port(args.port)
48
51
 
49
52
  if not is_arp_supported():
50
- log.warning('ARP is not supported, device discovery is degraded. For more information, see the help guide: https://github.com/mdennis281/LANscape/blob/main/support/arp-issues.md')
53
+ warn = (
54
+ 'ARP is not supported, device discovery is degraded. ',
55
+ 'For more information, see the help guide: ',
56
+ 'https://github.com/mdennis281/LANscape/blob/main/support/arp-issues.md'
57
+ )
58
+ log.warning(''.join(warn))
51
59
 
52
60
  try:
53
- start_webserver_ui(args)
61
+ start_webserver_ui()
54
62
  log.info('Exiting...')
55
63
  except Exception as e:
56
64
  # showing error in debug only because this is handled gracefully
@@ -60,6 +68,7 @@ def _main():
60
68
 
61
69
 
62
70
  def try_check_update():
71
+ """Check for updates and log if available."""
63
72
  try:
64
73
  if is_update_available():
65
74
  log.info('An update is available!')
@@ -86,7 +95,8 @@ def open_browser(url: str, wait=2) -> bool:
86
95
  return False
87
96
 
88
97
 
89
- def start_webserver_ui(args: RuntimeArgs):
98
+ def start_webserver_ui():
99
+ """Start the web server and open the UI in a browser."""
90
100
  uri = f'http://127.0.0.1:{args.port}'
91
101
 
92
102
  # running reloader requires flask to run in main thread
@@ -128,9 +138,9 @@ def get_valid_port(port: int):
128
138
 
129
139
 
130
140
  def terminate():
131
- import requests
141
+ """send a request to the shutdown flask"""
132
142
  log.info('Attempting flask shutdown')
133
- requests.get(f'http://127.0.0.1:{args.port}/shutdown?type=core')
143
+ requests.get(f'http://127.0.0.1:{args.port}/shutdown?type=core', timeout=2)
134
144
 
135
145
 
136
146
  if __name__ == "__main__":
@@ -0,0 +1,57 @@
1
+ """Logic for handling shutdown requests in a Flask application."""
2
+
3
+ import logging
4
+ import os
5
+ from flask import request
6
+
7
+
8
+ from lanscape.libraries.runtime_args import parse_args
9
+
10
+
11
+ log = logging.getLogger('shutdown_handler')
12
+
13
+
14
+ class FlaskShutdownHandler:
15
+ """Handles shutdown requests for the Flask application.
16
+ """
17
+
18
+ def __init__(self, app):
19
+ self.app = app
20
+ self._exiting = False
21
+
22
+ def register_endpoints(self):
23
+ """Register shutdown endpoints to the Flask app."""
24
+
25
+ @self.app.route('/shutdown', methods=['POST', 'GET'])
26
+ def shutdown():
27
+ req_type = request.args.get('type')
28
+ self.shutdown_request(req_type)
29
+ return "Done"
30
+
31
+ @self.app.teardown_request
32
+ def teardown(_):
33
+ self.exit_if_requested()
34
+
35
+ def shutdown_request(self, req_type: str):
36
+ """Handles shutdown requests based on the type of request.
37
+ Args:
38
+ req_type (str): The type of shutdown request.
39
+ """
40
+ if req_type == 'browser-close':
41
+ args = parse_args()
42
+ if args.persistent:
43
+ log.info('Detected browser close, not exiting flask.')
44
+ return "Ignored"
45
+ log.info(
46
+ 'Web browser closed, terminating flask. (disable with --persistent)')
47
+ elif req_type == 'core':
48
+ log.info('Core requested exit, terminating flask.')
49
+ else:
50
+ log.info('Received external exit request. Terminating flask.')
51
+ self._exiting = True
52
+ return "Done"
53
+
54
+ def exit_if_requested(self):
55
+ """Exits the application if a shutdown request has been made."""
56
+ if self._exiting:
57
+ os._exit(0)
@@ -117,6 +117,7 @@ hr {
117
117
  }
118
118
  h1.title{
119
119
  cursor: pointer;
120
+ margin: 0;
120
121
  }
121
122
  .title span {
122
123
  color: var(--text-accent-color);
@@ -163,18 +164,21 @@ details {
163
164
  border-radius: 5px !important; /* override bootstrap stuff */
164
165
  padding-right: 34px;
165
166
  margin-right: -34px;
167
+ margin-left: -41px;
168
+ padding-left: calc(41px + 5px);
166
169
  }
167
170
 
168
171
 
169
172
  #scan-form .input-group button {
170
173
  background-color: var(--primary-bg-accent);
171
174
  border: 0;
172
- border-left: 1px var(--border-color) solid;
175
+
173
176
  transition: all .2s ease-in-out;
174
177
  height: 40px;
175
- border-radius: 0 5px 5px 0;
176
178
  margin-top: 1px;
177
179
  transform: translateX(.5px);
180
+ z-index: 3;
181
+ margin-left: 0;
178
182
  }
179
183
  #scan-form .input-group button:hover {
180
184
  background-color: var(--primary-bg-accent-hover);
@@ -182,6 +186,15 @@ details {
182
186
  #scan-form .input-group button:active {
183
187
  background-color: var(--primary-accent);
184
188
  }
189
+ #scan-form .input-group button.start {
190
+ border-radius: 5px 0 0 5px;
191
+ border-right: 1px var(--border-color) solid;
192
+ width: 40px; /* added because it looks gross on icon load */
193
+ }
194
+ #scan-form .input-group button.end {
195
+ border-radius: 0 5px 5px 0;
196
+ border-left: 1px var(--border-color) solid;
197
+ }
185
198
 
186
199
  .label-container {
187
200
  display: flex;
@@ -256,8 +269,69 @@ details {
256
269
  }
257
270
  }
258
271
 
272
+ #advanced-modal {
273
+ --bs-modal-width: 750px;
274
+ }
275
+ #advanced-modal .modal-content {
276
+ background-color: var(--primary-bg);
277
+ }
278
+ #advanced-modal .descriptor {
279
+ align-content: end;
280
+ text-align: center;
281
+ color: var(--text-placeholder);
282
+ padding-bottom: 10px;
283
+ }
284
+ #advanced-modal .col-2-percent {
285
+ flex: 0 0 auto;
286
+ width: 2%;
287
+ }
288
+ #advanced-modal label {
289
+ font-size: 12px;
290
+ }
291
+ #advanced-modal .form-check {
292
+ width: fit-content;
293
+ }
294
+ #advanced-modal h6 {
295
+ color: var(--primary-accent);
296
+ }
297
+ #advanced-modal .config-option {
298
+ background-color: var(--primary-bg-accent);
299
+ border: 1px solid var(--border-color);
300
+ border-radius: 5px;
301
+ cursor: pointer;
302
+ text-align: center;
303
+ margin: 0 5px;
304
+ transition: all .2s ease-in-out;
305
+ }
259
306
 
260
-
307
+ #advanced-modal .config-option.active {
308
+ border-color: var(--primary-accent);
309
+ box-shadow: 0 0 5px var(--primary-accent);
310
+ background-color: var(--primary-bg);
311
+ }
312
+ #advanced-modal .config-option:hover {
313
+ background-color: var(--primary-bg);
314
+ box-shadow: 0 0 5px var(--primary-accent);
315
+ }
316
+ #advanced-modal .config-option.active:hover {
317
+ background-color: var(--primary-bg-accent);
318
+ box-shadow: 0 0 5px var(--primary-accent);
319
+ }
320
+ #advanced-modal .config-option h5 {
321
+ flex-wrap: wrap;
322
+ }
323
+ #advanced-modal .config-option h5 span {
324
+ display: block; /* "waaaah span shouldnt be block" bite me. */
325
+ width: 100%;
326
+ padding: 5px;
327
+ font-size: 2em;
328
+ }
329
+ #advanced-modal .config-option p {
330
+ font-size: 0.8em;
331
+ color: var(--text-placeholder);
332
+ margin: 0;
333
+ padding: 5px;
334
+ }
261
335
 
262
336
 
263
337
  /* Card Styles */
@@ -286,7 +360,7 @@ form {
286
360
  flex-grow: 1;
287
361
  display: flex;
288
362
  flex-direction: column;
289
- margin-bottom: 15px;
363
+ margin-bottom: 5px;
290
364
  }
291
365
 
292
366
  label {
@@ -310,6 +384,12 @@ input[type="text"]:focus, select:focus, .form-control:focus {
310
384
  border-color: var(--primary-accent);
311
385
  outline: none;
312
386
  }
387
+ input[type="text"]:read-only, .form-control:read-only {
388
+ background-color: var(--secondary-bg);
389
+ color: var(--text-placeholder);
390
+ border-color: var(--secondary-accent);
391
+ outline: none;
392
+ }
313
393
 
314
394
  input::placeholder {
315
395
  color: var(--text-placeholder) !important;
@@ -326,6 +406,7 @@ button {
326
406
  #scan-form #scan-submit {
327
407
  border: none;
328
408
  padding: 10px 20px;
409
+ margin-top: 15px;
329
410
  }
330
411
 
331
412
  /* Button Styling */
@@ -378,20 +459,6 @@ input[type="range"] {
378
459
  margin: 5px 0;
379
460
  }
380
461
 
381
- input[type="range"]::-webkit-slider-thumb,
382
- input[type="range"]::-moz-range-thumb {
383
- -webkit-appearance: none;
384
- appearance: none;
385
- width: 16px;
386
- height: 16px;
387
- border-radius: 50%;
388
- background: var(--primary-accent);
389
- cursor: pointer;
390
- }
391
- #parallelism-value span {
392
- color: var(--text-danger-color);
393
- font-weight: 500;
394
- }
395
462
  .port-list-wrapper {
396
463
  position: relative;
397
464
  display: inline-block;
@@ -400,12 +467,13 @@ input[type="range"]::-moz-range-thumb {
400
467
 
401
468
  .port-list {
402
469
  position: relative;
403
- background-color: var(--body-bg);
470
+ background-color: var(--secondary-bg);
404
471
  border: 1px solid var(--border-color);
405
472
  color: var(--text-color);
406
473
  padding: 10px;
407
474
  cursor: pointer;
408
475
  width: 100%;
476
+ height: 42px;
409
477
  user-select: none;
410
478
  appearance: none; /* Hide default arrow */
411
479
  transition: all .2s ease-in-out;
@@ -419,7 +487,7 @@ input[type="range"]::-moz-range-thumb {
419
487
  .port-list-wrapper::after {
420
488
  content: '▼';
421
489
  position: absolute;
422
- top: 14px;
490
+ top: 10px;
423
491
  right: 10px;
424
492
  pointer-events: none;
425
493
  color: var(--text-color);
@@ -451,6 +519,12 @@ input[type="range"]::-moz-range-thumb {
451
519
  color: var(--text-color);
452
520
  }
453
521
 
522
+
523
+
524
+ .text-color {
525
+ color: var(--text-color) !important;
526
+ }
527
+
454
528
  .text-secondary {
455
529
  color: var(--secondary-accent) !important;
456
530
  }
@@ -2,21 +2,15 @@
2
2
 
3
3
  $(document).ready(function() {
4
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
5
  const scanId = getActiveScanId();
17
6
  if (scanId) {
18
7
  showScan(scanId);
19
8
  }
9
+
10
+ // this prevents the browser from
11
+ // triggering the shutdown beacon
12
+ // when user clicks the logo
13
+ setUrlParam('loaded', 'true')
20
14
 
21
15
 
22
16
  // Handle form submission
@@ -39,18 +33,19 @@ $(document).ready(function() {
39
33
  $('#ip-table-frame').attr('src', newSrc);
40
34
  });
41
35
 
36
+ $('#settings-btn').on('click', function() {
37
+ $('#advanced-modal').modal('show');
38
+ });
39
+
42
40
  });
43
41
 
44
42
  function submitNewScan() {
45
- const formData = {
46
- subnet: $('#subnet').val(),
47
- port_list: $('#port-list').text(),
48
- parallelism: $('#parallelism').val()
49
- };
43
+ const config = getScanConfig();
44
+ config.subnet = $('#subnet').val();
50
45
  $.ajax('/api/scan', {
51
- data : JSON.stringify(formData),
52
- contentType : 'application/json',
53
- type : 'POST',
46
+ data: JSON.stringify(config),
47
+ contentType: 'application/json',
48
+ type: 'POST',
54
49
  success: function(response) {
55
50
  if (response.status === 'running') {
56
51
  showScan(response.scan_id);
@@ -75,37 +70,9 @@ function showScan(scanId) {
75
70
  //$('#overview-frame').attr('src', '/scan/' + scanId + '/overview');
76
71
  $('#ip-table-frame').attr('src', '/scan/' + scanId + '/table');
77
72
 
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);
73
+ setUrlParam('scan_id', scanId);
83
74
  }
84
75
 
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
76
 
110
77
  $(document).on('click', function(event) {
111
78
  if (!$(event.target).closest('.port-list-wrapper').length) {
@@ -234,6 +201,16 @@ $('#ip-table-frame').on('load', function() {
234
201
  observeIframeContent(this); // Start observing for dynamic changes
235
202
  });
236
203
 
204
+ function setUrlParam(param, value) {
205
+ const url = new URL(window.location.href);
206
+ if (value === null || value === undefined) {
207
+ url.searchParams.delete(param);
208
+ } else {
209
+ url.searchParams.set(param, value);
210
+ }
211
+ window.history.pushState({}, '', url);
212
+ }
213
+
237
214
 
238
215
 
239
216
  $(window).on('resize', function() {
@@ -0,0 +1,107 @@
1
+ let defaultScanConfigs = {};
2
+ let activeConfigName = 'balanced';
3
+
4
+ $(document).ready(function() {
5
+ // load port lists
6
+ getPortLists(function() {
7
+ // THEN get scan config defaults
8
+ getScanDefaults(function() {
9
+ // THEN set the default scan config
10
+ setScanConfig('balanced');
11
+ })
12
+ });
13
+
14
+ $('#t_cnt_port_scan, #t_cnt_port_test').on('input', updatePortTotals);
15
+ $('#ping_attempts, #ping_ping_count').on('input', updatePingTotals);
16
+ });
17
+
18
+ function getScanDefaults(callback=null) {
19
+ $.getJSON('/api/tools/config/defaults', (data) => {
20
+ defaultScanConfigs = data;
21
+ if (callback) callback();
22
+ });
23
+ }
24
+
25
+ function setScanConfig(configName) {
26
+ const config = defaultScanConfigs[configName];
27
+ if (!config) return;
28
+ activeConfigName = configName;
29
+
30
+ // highlight selected preset
31
+ $('.config-option').removeClass('active');
32
+ $(`#config-${configName}`).addClass('active');
33
+
34
+ // basic settings
35
+ $('#port_list').val(config.port_list);
36
+ $('#t_multiplier').val(config.t_multiplier);
37
+ $('#t_cnt_port_scan').val(config.t_cnt_port_scan);
38
+ $('#t_cnt_port_test').val(config.t_cnt_port_test);
39
+ $('#t_cnt_isalive').val(config.t_cnt_isalive);
40
+ $('#task_scan_ports').prop('checked', config.task_scan_ports);
41
+ $('#task_scan_port_services').prop('checked', config.task_scan_port_services);
42
+ $('#lookup_type').val(config.lookup_type);
43
+
44
+ // ping config
45
+ $('#ping_attempts').val(config.ping_config.attempts);
46
+ $('#ping_ping_count').val(config.ping_config.ping_count);
47
+ $('#ping_retry_delay').val(config.ping_config.retry_delay);
48
+ $('#ping_timeout').val(config.ping_config.timeout);
49
+
50
+ // arp config
51
+ $('#arp_attempts').val(config.arp_config.attempts);
52
+ $('#arp_timeout').val(config.arp_config.timeout);
53
+
54
+ updatePortTotals();
55
+ updatePingTotals();
56
+ }
57
+
58
+ function getScanConfig() {
59
+ return {
60
+ port_list: $('#port_list').val(),
61
+ t_cnt_port_scan: parseInt($('#t_cnt_port_scan').val()),
62
+ t_cnt_port_test: parseInt($('#t_cnt_port_test').val()),
63
+ t_cnt_isalive: parseInt($('#t_cnt_isalive').val()),
64
+ task_scan_ports: $('#task_scan_ports').is(':checked'),
65
+ task_scan_port_services: $('#task_scan_port_services').is(':checked'),
66
+ lookup_type: $('#lookup_type').val(),
67
+ ping_config: {
68
+ attempts: parseInt($('#ping_attempts').val()),
69
+ ping_count: parseInt($('#ping_ping_count').val()),
70
+ retry_delay: parseFloat($('#ping_retry_delay').val()),
71
+ timeout: parseFloat($('#ping_timeout').val())
72
+ },
73
+ arp_config: {
74
+ attempts: parseInt($('#arp_attempts').val()),
75
+ timeout: parseFloat($('#arp_timeout').val())
76
+ }
77
+ };
78
+ }
79
+
80
+ function getPortLists(callback=null) {
81
+ $.get('/api/port/list', function(data) {
82
+ const customSelectDropdown = $('#port_list');
83
+ customSelectDropdown.empty();
84
+
85
+ // Populate the dropdown with the options
86
+ data.forEach(function(portList) {
87
+ customSelectDropdown.append('<option>' + portList + '</option>');
88
+ });
89
+ if (callback) callback();
90
+ });
91
+ }
92
+
93
+ function updatePortTotals() {
94
+ const scan = parseInt($('#t_cnt_port_scan').val()) || 0;
95
+ const test = parseInt($('#t_cnt_port_test').val()) || 0;
96
+ $('#total-port-tests').val(scan * test);
97
+ }
98
+
99
+ function updatePingTotals() {
100
+ const attempts = parseInt($('#ping_attempts').val()) || 0;
101
+ const count = parseInt($('#ping_ping_count').val()) || 0;
102
+ $('#total-ping-attempts').val(attempts * count);
103
+ }
104
+
105
+ // expose functions globally
106
+ window.setScanConfig = setScanConfig;
107
+ window.getScanConfig = getScanConfig;
@@ -13,7 +13,8 @@
13
13
  "type": "image/png"
14
14
  }
15
15
  ],
16
- "theme_color": "#0856a9",
17
- "background_color": "#1e1e1e",
18
- "display": "standalone"
16
+ "theme_color": "#0a84ff",
17
+ "background_color": "#262626",
18
+ "display": "minimal-ui"
19
+
19
20
  }