lanscape 1.3.8b1__tar.gz → 1.4.0__tar.gz
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.
Potentially problematic release.
This version of lanscape might be problematic. Click here for more details.
- {lanscape-1.3.8b1/lanscape.egg-info → lanscape-1.4.0}/PKG-INFO +1 -1
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/decorators.py +29 -3
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/net_tools.py +10 -25
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/version_manager.py +15 -18
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/css/style.css +8 -0
- lanscape-1.4.0/lanscape/ui/templates/scan/config.html +221 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0/lanscape.egg-info}/PKG-INFO +1 -1
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape.egg-info/SOURCES.txt +1 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/pyproject.toml +1 -1
- lanscape-1.4.0/tests/test_decorators.py +29 -0
- lanscape-1.3.8b1/lanscape/ui/templates/scan/config.html +0 -229
- {lanscape-1.3.8b1 → lanscape-1.4.0}/LICENSE +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/MANIFEST.in +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/README.md +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/__init__.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/__main__.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/__init__.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/app_scope.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/device_alive.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/errors.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/ip_parser.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/logger.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/mac_lookup.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/port_manager.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/runtime_args.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/scan_config.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/service_scan.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/subnet_scan.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/web_browser.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/mac_addresses/convert_csv.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/mac_addresses/mac_db.json +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/convert_csv.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/full.json +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/large.json +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/medium.json +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/small.json +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/services/definitions.jsonc +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/__init__.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/app.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/__init__.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/api/__init__.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/api/port.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/api/scan.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/api/tools.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/web/__init__.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/web/routes.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/main.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/shutdown_handler.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/android-chrome-192x192.png +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/android-chrome-512x512.png +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/apple-touch-icon.png +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/favicon-16x16.png +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/favicon-32x32.png +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/favicon.ico +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/site.webmanifest +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/core.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/layout-sizing.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/main.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/on-tab-close.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/quietReload.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/scan-config.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/shutdown-server.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/subnet-info.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/subnet-selector.js +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/lanscape.webmanifest +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/base.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/core/head.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/core/scripts.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/error.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/info.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/main.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/export.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/ip-table-row.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/ip-table.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/overview.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/scan-error.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/shutdown.html +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape.egg-info/dependency_links.txt +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape.egg-info/requires.txt +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape.egg-info/top_level.txt +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/setup.cfg +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_api.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_env.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_library.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_logging.py +0 -0
- {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_utils.py +0 -0
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
"""
|
|
3
|
-
Decorators and job tracking utilities for Lanscape.
|
|
4
|
-
"""
|
|
2
|
+
"""Decorators and job tracking utilities for Lanscape."""
|
|
5
3
|
|
|
6
4
|
from time import time
|
|
7
5
|
from dataclasses import dataclass, field
|
|
@@ -10,9 +8,37 @@ from collections import defaultdict
|
|
|
10
8
|
import inspect
|
|
11
9
|
import functools
|
|
12
10
|
import concurrent.futures
|
|
11
|
+
import logging
|
|
13
12
|
from tabulate import tabulate
|
|
14
13
|
|
|
15
14
|
|
|
15
|
+
log = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_once(func):
|
|
19
|
+
"""Ensure a function executes only once and cache the result."""
|
|
20
|
+
|
|
21
|
+
cache_attr = "_run_once_cache"
|
|
22
|
+
ran_attr = "_run_once_ran"
|
|
23
|
+
|
|
24
|
+
@functools.wraps(func)
|
|
25
|
+
def wrapper(*args, **kwargs):
|
|
26
|
+
if getattr(wrapper, ran_attr, False):
|
|
27
|
+
return getattr(wrapper, cache_attr)
|
|
28
|
+
|
|
29
|
+
start = time()
|
|
30
|
+
result = func(*args, **kwargs)
|
|
31
|
+
elapsed = time() - start
|
|
32
|
+
|
|
33
|
+
setattr(wrapper, cache_attr, result)
|
|
34
|
+
setattr(wrapper, ran_attr, True)
|
|
35
|
+
|
|
36
|
+
log.debug("run_once executed %s in %.4fs", func.__qualname__, elapsed)
|
|
37
|
+
return result
|
|
38
|
+
|
|
39
|
+
return wrapper
|
|
40
|
+
|
|
41
|
+
|
|
16
42
|
@dataclass
|
|
17
43
|
class JobStats:
|
|
18
44
|
"""
|
|
@@ -18,7 +18,7 @@ from lanscape.libraries.service_scan import scan_service
|
|
|
18
18
|
from lanscape.libraries.mac_lookup import MacLookup, get_macs
|
|
19
19
|
from lanscape.libraries.ip_parser import get_address_count, MAX_IPS_ALLOWED
|
|
20
20
|
from lanscape.libraries.errors import DeviceError
|
|
21
|
-
from lanscape.libraries.decorators import job_tracker
|
|
21
|
+
from lanscape.libraries.decorators import job_tracker, run_once
|
|
22
22
|
|
|
23
23
|
log = logging.getLogger('NetTools')
|
|
24
24
|
mac_lookup = MacLookup()
|
|
@@ -459,32 +459,17 @@ def smart_select_primary_subnet(subnets: List[dict] = None) -> str:
|
|
|
459
459
|
return selected.get("subnet", "")
|
|
460
460
|
|
|
461
461
|
|
|
462
|
-
|
|
463
|
-
"""
|
|
464
|
-
Singleton class to check if ARP requests are supported on the current system.
|
|
465
|
-
The check is only performed once.
|
|
466
|
-
"""
|
|
467
|
-
_supported = None
|
|
468
|
-
|
|
469
|
-
@classmethod
|
|
470
|
-
def is_supported(cls):
|
|
471
|
-
"""one time check if ARP requests are supported on this system"""
|
|
472
|
-
if cls._supported is not None:
|
|
473
|
-
return cls._supported
|
|
474
|
-
try:
|
|
475
|
-
arp_request = ARP(pdst='0.0.0.0')
|
|
476
|
-
broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
|
|
477
|
-
packet = broadcast / arp_request
|
|
478
|
-
srp(packet, timeout=0, verbose=False)
|
|
479
|
-
cls._supported = True
|
|
480
|
-
except (Scapy_Exception, PermissionError, RuntimeError):
|
|
481
|
-
cls._supported = False
|
|
482
|
-
return cls._supported
|
|
483
|
-
|
|
484
|
-
|
|
462
|
+
@run_once
|
|
485
463
|
def is_arp_supported():
|
|
486
464
|
"""
|
|
487
465
|
Check if ARP requests are supported on the current system.
|
|
488
466
|
Only runs the check once.
|
|
489
467
|
"""
|
|
490
|
-
|
|
468
|
+
try:
|
|
469
|
+
arp_request = ARP(pdst='0.0.0.0')
|
|
470
|
+
broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
|
|
471
|
+
packet = broadcast / arp_request
|
|
472
|
+
srp(packet, timeout=0, verbose=False)
|
|
473
|
+
return True
|
|
474
|
+
except (Scapy_Exception, PermissionError, RuntimeError):
|
|
475
|
+
return False
|
|
@@ -11,17 +11,14 @@ from random import randint
|
|
|
11
11
|
|
|
12
12
|
import requests
|
|
13
13
|
|
|
14
|
-
from .app_scope import is_local_run
|
|
14
|
+
from lanscape.libraries.app_scope import is_local_run
|
|
15
|
+
from lanscape.libraries.decorators import run_once
|
|
15
16
|
|
|
16
17
|
log = logging.getLogger('VersionManager')
|
|
17
18
|
|
|
18
19
|
PACKAGE = 'lanscape'
|
|
19
20
|
LOCAL_VERSION = '0.0.0'
|
|
20
21
|
|
|
21
|
-
# Used to cache PyPI version during runtime
|
|
22
|
-
LATEST_VERSION = None
|
|
23
|
-
|
|
24
|
-
|
|
25
22
|
def is_update_available(package=PACKAGE) -> bool:
|
|
26
23
|
"""
|
|
27
24
|
Check if an update is available for the package.
|
|
@@ -49,6 +46,7 @@ def is_update_available(package=PACKAGE) -> bool:
|
|
|
49
46
|
return installed != available
|
|
50
47
|
|
|
51
48
|
|
|
49
|
+
@run_once
|
|
52
50
|
def lookup_latest_version(package=PACKAGE):
|
|
53
51
|
"""
|
|
54
52
|
Retrieve the latest version of the package from PyPI.
|
|
@@ -62,19 +60,18 @@ def lookup_latest_version(package=PACKAGE):
|
|
|
62
60
|
The latest version string from PyPI or None if retrieval fails
|
|
63
61
|
"""
|
|
64
62
|
# Fetch the latest version from PyPI
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return LATEST_VERSION
|
|
63
|
+
no_cache = f'?cachebust={randint(0, 6969)}'
|
|
64
|
+
url = f"https://pypi.org/pypi/{package}/json{no_cache}"
|
|
65
|
+
try:
|
|
66
|
+
response = requests.get(url, timeout=3)
|
|
67
|
+
response.raise_for_status() # Raise an exception for HTTP errors
|
|
68
|
+
latest_version = response.json()['info']['version']
|
|
69
|
+
log.debug(f'Latest pypi version: {latest_version}')
|
|
70
|
+
return latest_version
|
|
71
|
+
except BaseException:
|
|
72
|
+
log.debug(traceback.format_exc())
|
|
73
|
+
log.warning('Unable to fetch package version from PyPi')
|
|
74
|
+
return None
|
|
78
75
|
|
|
79
76
|
|
|
80
77
|
def get_installed_version(package=PACKAGE):
|
|
@@ -115,6 +115,14 @@ hr {
|
|
|
115
115
|
border-color: var(--border-color);
|
|
116
116
|
margin: 20px 0;
|
|
117
117
|
}
|
|
118
|
+
|
|
119
|
+
.config-sections > .config-section {
|
|
120
|
+
border-top: 1px solid var(--border-color);
|
|
121
|
+
margin-top: 20px;
|
|
122
|
+
padding-top: 20px;
|
|
123
|
+
padding-bottom: 20px;
|
|
124
|
+
}
|
|
125
|
+
|
|
118
126
|
h1.title{
|
|
119
127
|
cursor: pointer;
|
|
120
128
|
margin: 0;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
<div class="modal fade" id="advanced-modal" tabindex="-1" aria-hidden="true">
|
|
2
|
+
<div class="modal-dialog">
|
|
3
|
+
<div class="modal-content">
|
|
4
|
+
<div class="modal-header border-secondary">
|
|
5
|
+
<h5 class="modal-title" id="advanced-modalLabel">Advanced Settings</h5>
|
|
6
|
+
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="modal-body">
|
|
9
|
+
<div class="d-flex gap-2 mb-3">
|
|
10
|
+
<div class="config-option p-3 flex-fill flex-wrap" id="config-fast" data-config="fast" onclick="setScanConfig('fast')">
|
|
11
|
+
<h5 class="mb-1 d-flex align-items-center justify-content-center">
|
|
12
|
+
<span class="material-symbols-outlined me-1">bolt</span>Fast
|
|
13
|
+
</h5>
|
|
14
|
+
<p class="mb-0">Fast scan, Low accuracy</p>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="config-option p-3 flex-fill" id="config-balanced" data-config="balanced" onclick="setScanConfig('balanced')">
|
|
17
|
+
<h5 class="mb-1 d-flex align-items-center justify-content-center">
|
|
18
|
+
<span class="material-symbols-outlined me-1">balance</span>Balanced
|
|
19
|
+
</h5>
|
|
20
|
+
<p class="mb-0">Balanced scan, Moderate accuracy</p>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="config-option p-3 flex-fill" id="config-accurate" data-config="accurate" onclick="setScanConfig('accurate')">
|
|
23
|
+
<h5 class="mb-1 d-flex align-items-center justify-content-center">
|
|
24
|
+
<span class="material-symbols-outlined me-1">target</span>Accurate
|
|
25
|
+
</h5>
|
|
26
|
+
<p class="mb-0">Thorough scan, High accuracy</p>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="config-sections">
|
|
31
|
+
<div class="form-group mt-2 config-section">
|
|
32
|
+
<h6>Device Detection</h6>
|
|
33
|
+
<div class="row mt-2">
|
|
34
|
+
<div class="col">
|
|
35
|
+
<label class="mb-1">Lookup Type</label>
|
|
36
|
+
<div id="lookup-type-group" class="d-flex flex-wrap gap-3">
|
|
37
|
+
<div class="form-check">
|
|
38
|
+
<input class="form-check-input lookup-type-input" type="checkbox" id="lookup_icmp" value="ICMP">
|
|
39
|
+
<label class="form-check-label" for="lookup_icmp">ICMP</label>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="form-check">
|
|
42
|
+
<!-- ARP lookup does not always work. Depends on host system -->
|
|
43
|
+
<input
|
|
44
|
+
class="form-check-input lookup-type-input"
|
|
45
|
+
type="checkbox"
|
|
46
|
+
id="lookup_arp_lookup"
|
|
47
|
+
value="ARP_LOOKUP"
|
|
48
|
+
{{ '' if is_arp_supported else 'disabled' }}
|
|
49
|
+
/>
|
|
50
|
+
<label class="form-check-label" for="lookup_arp_lookup">
|
|
51
|
+
ARP Lookup
|
|
52
|
+
</label>
|
|
53
|
+
{% if not is_arp_supported %}
|
|
54
|
+
<span
|
|
55
|
+
class="material-symbols-outlined arp-help-ico"
|
|
56
|
+
data-bs-toggle="tooltip"
|
|
57
|
+
data-bs-placement="top"
|
|
58
|
+
title="ARP lookup is not supported on this system, click for more info"
|
|
59
|
+
onclick="window.open('https://github.com/mdennis281/LANscape/blob/main/support/arp-issues.md', '_blank')"
|
|
60
|
+
>
|
|
61
|
+
help
|
|
62
|
+
</span>
|
|
63
|
+
{% endif %}
|
|
64
|
+
</div>
|
|
65
|
+
<div class="form-check">
|
|
66
|
+
<input class="form-check-input lookup-type-input" type="checkbox" id="lookup_icmp_then_arp" value="ICMP_THEN_ARP">
|
|
67
|
+
<label class="form-check-label" for="lookup_icmp_then_arp">ICMP then ARP Cache</label>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="form-check">
|
|
70
|
+
<input class="form-check-input lookup-type-input" type="checkbox" id="lookup_poke_then_arp" value="POKE_THEN_ARP">
|
|
71
|
+
<label class="form-check-label" for="lookup_poke_then_arp">Poke then ARP Cache</label>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="col">
|
|
76
|
+
<label for="t_cnt_isalive">Device Lookup Threads</label>
|
|
77
|
+
<input type="number" id="t_cnt_isalive" class="form-control">
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div id="section-ping" class="form-group mt-2 config-section">
|
|
83
|
+
<h6>Device Detection <span class=text-color>/</span> Ping Settings</h6>
|
|
84
|
+
<div class="row">
|
|
85
|
+
<div class="col-3">
|
|
86
|
+
<label for="ping_attempts" class="form-label">Ping Attempts</label>
|
|
87
|
+
<input type="number" id="ping_attempts" class="form-control">
|
|
88
|
+
</div>
|
|
89
|
+
<div class="col-1 descriptor">X</div>
|
|
90
|
+
<div class="col-3">
|
|
91
|
+
<label for="ping_ping_count" class="form-label">Ping Count</label>
|
|
92
|
+
<input type="number" id="ping_ping_count" class="form-control">
|
|
93
|
+
</div>
|
|
94
|
+
<div class="col-1 descriptor">=</div>
|
|
95
|
+
<div class="col-3">
|
|
96
|
+
<label for="total-ping-attempts">Max pings per device</label>
|
|
97
|
+
<input type="number" id="total-ping-attempts" class="form-control" readonly>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="row mt-2">
|
|
101
|
+
<div class="col">
|
|
102
|
+
<label for="ping_timeout" class="form-label">Timeout Per Ping (sec)</label>
|
|
103
|
+
<input type="number" step="0.1" id="ping_timeout" class="form-control">
|
|
104
|
+
</div>
|
|
105
|
+
<div class="col">
|
|
106
|
+
<label for="ping_retry_delay" class="form-label">Delay Between Attempts (sec)</label>
|
|
107
|
+
<input type="number" step="0.1" id="ping_retry_delay" class="form-control">
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div id="section-arp" class="form-group mt-2 config-section">
|
|
113
|
+
<h6>Device Detection <span class=text-color>/</span> ARP Settings</h6>
|
|
114
|
+
<div class="row">
|
|
115
|
+
<div class="col">
|
|
116
|
+
<label for="arp_attempts" class="form-label">Attempts</label>
|
|
117
|
+
<input type="number" id="arp_attempts" class="form-control">
|
|
118
|
+
</div>
|
|
119
|
+
<div class="col">
|
|
120
|
+
<label for="arp_timeout" class="form-label">Timeout</label>
|
|
121
|
+
<input type="number" step="0.1" id="arp_timeout" class="form-control">
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<div id="section-arp-cache" class="form-group mt-2 div-hide config-section">
|
|
127
|
+
<h6>Device Detection <span class=text-color>/</span> ARP Cache Settings</h6>
|
|
128
|
+
<div class="row">
|
|
129
|
+
<div class="col">
|
|
130
|
+
<label for="arp_cache_attempts" class="form-label">Attempts</label>
|
|
131
|
+
<input type="number" id="arp_cache_attempts" class="form-control">
|
|
132
|
+
</div>
|
|
133
|
+
<div class="col">
|
|
134
|
+
<label for="arp_cache_wait_before" class="form-label">Wait Before (sec)</label>
|
|
135
|
+
<input type="number" step="0.1" id="arp_cache_wait_before" class="form-control">
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div id="section-poke" class="form-group mt-2 div-hide config-section">
|
|
141
|
+
<h6>Device Detection <span class=text-color>/</span> Poke Settings</h6>
|
|
142
|
+
<div class="row">
|
|
143
|
+
<div class="col">
|
|
144
|
+
<label for="poke_attempts" class="form-label">Attempts</label>
|
|
145
|
+
<input type="number" id="poke_attempts" class="form-control">
|
|
146
|
+
</div>
|
|
147
|
+
<div class="col">
|
|
148
|
+
<label for="poke_timeout" class="form-label">Timeout (sec)</label>
|
|
149
|
+
<input type="number" step="0.1" id="poke_timeout" class="form-control">
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<div class="form-group mt-2 config-section">
|
|
155
|
+
<h6>Port Testing</h6>
|
|
156
|
+
<div class="row">
|
|
157
|
+
<div class="col-3">
|
|
158
|
+
<label for="t_cnt_port_scan">Device Scan Threads</label>
|
|
159
|
+
<input type="number" id="t_cnt_port_scan" class="form-control">
|
|
160
|
+
</div>
|
|
161
|
+
<div class="col-1 descriptor">X</div>
|
|
162
|
+
<div class="col-3">
|
|
163
|
+
<label for="t_cnt_port_test">Port Test Threads</label>
|
|
164
|
+
<input type="number" id="t_cnt_port_test" class="form-control">
|
|
165
|
+
</div>
|
|
166
|
+
<div class="col-1 descriptor">=</div>
|
|
167
|
+
<div class="col-3">
|
|
168
|
+
<label for="total-port-tests">Total concurrent tests</label>
|
|
169
|
+
<input type="number" id="total-port-tests" class="form-control" readonly>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
<div class="row mt-2">
|
|
173
|
+
<div class="col">
|
|
174
|
+
<label for="port_list">Port List</label>
|
|
175
|
+
<div class="port-list-wrapper">
|
|
176
|
+
<select id="port_list" class="port-list">
|
|
177
|
+
<option value="both">ARP + Ping</option>
|
|
178
|
+
<option value="arp">ARP Only</option>
|
|
179
|
+
<option value="ping">Ping Only</option>
|
|
180
|
+
</select>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<div class="form-group mt-2 config-section">
|
|
187
|
+
<h6>Stages</h6>
|
|
188
|
+
<div class="form-check"
|
|
189
|
+
data-bs-toggle="tooltip"
|
|
190
|
+
data-bs-placement="right"
|
|
191
|
+
title="Find Devices using ARP or Ping (always on)"
|
|
192
|
+
>
|
|
193
|
+
<input class="form-check-input" disabled type="checkbox" id="task_find_devices" checked>
|
|
194
|
+
<label class="form-check-label" for="task_find_devices">Find Devices</label>
|
|
195
|
+
</div>
|
|
196
|
+
<div class="form-check"
|
|
197
|
+
data-bs-toggle="tooltip"
|
|
198
|
+
data-bs-placement="right"
|
|
199
|
+
title="Find open ports on devices"
|
|
200
|
+
>
|
|
201
|
+
<input class="form-check-input" type="checkbox" id="task_scan_ports">
|
|
202
|
+
<label class="form-check-label" for="task_scan_ports">Scan Ports</label>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="form-check"
|
|
205
|
+
data-bs-toggle="tooltip"
|
|
206
|
+
data-bs-placement="right"
|
|
207
|
+
title="Determine services running on open ports (no supporting UI yet)"
|
|
208
|
+
>
|
|
209
|
+
<input class="form-check-input" type="checkbox" id="task_scan_port_services">
|
|
210
|
+
<label class="form-check-label" for="task_scan_port_services">Scan Port Services</label>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
</div>
|
|
216
|
+
<div class="modal-footer border-secondary">
|
|
217
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Tests for helper decorators used throughout the project."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from lanscape.libraries.decorators import run_once
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_run_once_caches_result_and_logs_once(caplog):
|
|
9
|
+
"""run_once should execute only one time and cache the return value."""
|
|
10
|
+
|
|
11
|
+
caplog.set_level(logging.DEBUG)
|
|
12
|
+
|
|
13
|
+
call_count = {"count": 0}
|
|
14
|
+
|
|
15
|
+
@run_once
|
|
16
|
+
def sample_function(value):
|
|
17
|
+
call_count["count"] += 1
|
|
18
|
+
return value * 2
|
|
19
|
+
|
|
20
|
+
first = sample_function(3)
|
|
21
|
+
second = sample_function(5)
|
|
22
|
+
|
|
23
|
+
assert first == 6
|
|
24
|
+
assert second == 6
|
|
25
|
+
assert call_count["count"] == 1
|
|
26
|
+
|
|
27
|
+
messages = [record.message for record in caplog.records]
|
|
28
|
+
assert any("run_once executed" in record and "sample_function" in record for record in messages)
|
|
29
|
+
assert sum("run_once executed" in record for record in messages) == 1
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
<div class="modal fade" id="advanced-modal" tabindex="-1" aria-hidden="true">
|
|
2
|
-
<div class="modal-dialog">
|
|
3
|
-
<div class="modal-content">
|
|
4
|
-
<div class="modal-header border-secondary">
|
|
5
|
-
<h5 class="modal-title" id="advanced-modalLabel">Advanced Settings</h5>
|
|
6
|
-
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
7
|
-
</div>
|
|
8
|
-
<div class="modal-body">
|
|
9
|
-
<div class="d-flex gap-2 mb-3">
|
|
10
|
-
<div class="config-option p-3 flex-fill flex-wrap" id="config-fast" data-config="fast" onclick="setScanConfig('fast')">
|
|
11
|
-
<h5 class="mb-1 d-flex align-items-center justify-content-center">
|
|
12
|
-
<span class="material-symbols-outlined me-1">bolt</span>Fast
|
|
13
|
-
</h5>
|
|
14
|
-
<p class="mb-0">Fast scan, Low accuracy</p>
|
|
15
|
-
</div>
|
|
16
|
-
<div class="config-option p-3 flex-fill" id="config-balanced" data-config="balanced" onclick="setScanConfig('balanced')">
|
|
17
|
-
<h5 class="mb-1 d-flex align-items-center justify-content-center">
|
|
18
|
-
<span class="material-symbols-outlined me-1">balance</span>Balanced
|
|
19
|
-
</h5>
|
|
20
|
-
<p class="mb-0">Balanced scan, Moderate accuracy</p>
|
|
21
|
-
</div>
|
|
22
|
-
<div class="config-option p-3 flex-fill" id="config-accurate" data-config="accurate" onclick="setScanConfig('accurate')">
|
|
23
|
-
<h5 class="mb-1 d-flex align-items-center justify-content-center">
|
|
24
|
-
<span class="material-symbols-outlined me-1">target</span>Accurate
|
|
25
|
-
</h5>
|
|
26
|
-
<p class="mb-0">Thorough scan, High accuracy</p>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<hr>
|
|
31
|
-
<div class="form-group mt-2">
|
|
32
|
-
<h6>Device Detection</h6>
|
|
33
|
-
<div class="row mt-2">
|
|
34
|
-
<div class="col">
|
|
35
|
-
<label class="mb-1">Lookup Type</label>
|
|
36
|
-
<div id="lookup-type-group" class="d-flex flex-wrap gap-3">
|
|
37
|
-
<div class="form-check">
|
|
38
|
-
<input class="form-check-input lookup-type-input" type="checkbox" id="lookup_icmp" value="ICMP">
|
|
39
|
-
<label class="form-check-label" for="lookup_icmp">ICMP</label>
|
|
40
|
-
</div>
|
|
41
|
-
<div class="form-check">
|
|
42
|
-
<!-- ARP lookup does not always work. Depends on host system -->
|
|
43
|
-
<input
|
|
44
|
-
class="form-check-input lookup-type-input"
|
|
45
|
-
type="checkbox"
|
|
46
|
-
id="lookup_arp_lookup"
|
|
47
|
-
value="ARP_LOOKUP"
|
|
48
|
-
{{ '' if is_arp_supported else 'disabled' }}
|
|
49
|
-
/>
|
|
50
|
-
<label class="form-check-label" for="lookup_arp_lookup">
|
|
51
|
-
ARP Lookup
|
|
52
|
-
</label>
|
|
53
|
-
{% if not is_arp_supported %}
|
|
54
|
-
<span
|
|
55
|
-
class="material-symbols-outlined arp-help-ico"
|
|
56
|
-
data-bs-toggle="tooltip"
|
|
57
|
-
data-bs-placement="top"
|
|
58
|
-
title="ARP lookup is not supported on this system, click for more info"
|
|
59
|
-
onclick="window.open('https://github.com/mdennis281/LANscape/blob/main/support/arp-issues.md', '_blank')"
|
|
60
|
-
>
|
|
61
|
-
help
|
|
62
|
-
</span>
|
|
63
|
-
{% endif %}
|
|
64
|
-
</div>
|
|
65
|
-
<div class="form-check">
|
|
66
|
-
<input class="form-check-input lookup-type-input" type="checkbox" id="lookup_icmp_then_arp" value="ICMP_THEN_ARP">
|
|
67
|
-
<label class="form-check-label" for="lookup_icmp_then_arp">ICMP then ARP Cache</label>
|
|
68
|
-
</div>
|
|
69
|
-
<div class="form-check">
|
|
70
|
-
<input class="form-check-input lookup-type-input" type="checkbox" id="lookup_poke_then_arp" value="POKE_THEN_ARP">
|
|
71
|
-
<label class="form-check-label" for="lookup_poke_then_arp">Poke then ARP Cache</label>
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
</div>
|
|
76
|
-
<div class="col">
|
|
77
|
-
<label for="t_cnt_isalive">Device Lookup Threads</label>
|
|
78
|
-
<input type="number" id="t_cnt_isalive" class="form-control">
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
<hr>
|
|
84
|
-
<div id="section-ping" class="form-group mt-2">
|
|
85
|
-
<h6>Device Detection <span class=text-color>/</span> Ping Settings</h6>
|
|
86
|
-
<div class="row">
|
|
87
|
-
<div class="col-3">
|
|
88
|
-
<label for="ping_attempts" class="form-label">Ping Attempts</label>
|
|
89
|
-
<input type="number" id="ping_attempts" class="form-control">
|
|
90
|
-
</div>
|
|
91
|
-
<div class="col-1 descriptor">X</div>
|
|
92
|
-
<div class="col-3">
|
|
93
|
-
<label for="ping_ping_count" class="form-label">Ping Count</label>
|
|
94
|
-
<input type="number" id="ping_ping_count" class="form-control">
|
|
95
|
-
</div>
|
|
96
|
-
<div class="col-1 descriptor">=</div>
|
|
97
|
-
<div class="col-3">
|
|
98
|
-
<label for="total-ping-attempts">Max pings per device</label>
|
|
99
|
-
<input type="number" id="total-ping-attempts" class="form-control" readonly>
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
<div class="row mt-2">
|
|
103
|
-
<div class="col">
|
|
104
|
-
<label for="ping_timeout" class="form-label">Timeout Per Ping (sec)</label>
|
|
105
|
-
<input type="number" step="0.1" id="ping_timeout" class="form-control">
|
|
106
|
-
</div>
|
|
107
|
-
<div class="col">
|
|
108
|
-
<label for="ping_retry_delay" class="form-label">Delay Between Attempts (sec)</label>
|
|
109
|
-
<input type="number" step="0.1" id="ping_retry_delay" class="form-control">
|
|
110
|
-
</div>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
|
|
114
|
-
<hr>
|
|
115
|
-
<div id="section-arp" class="form-group mt-2">
|
|
116
|
-
<h6>Device Detection <span class=text-color>/</span> ARP Settings</h6>
|
|
117
|
-
<div class="row">
|
|
118
|
-
<div class="col">
|
|
119
|
-
<label for="arp_attempts" class="form-label">Attempts</label>
|
|
120
|
-
<input type="number" id="arp_attempts" class="form-control">
|
|
121
|
-
</div>
|
|
122
|
-
<div class="col">
|
|
123
|
-
<label for="arp_timeout" class="form-label">Timeout</label>
|
|
124
|
-
<input type="number" step="0.1" id="arp_timeout" class="form-control">
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
</div>
|
|
128
|
-
|
|
129
|
-
<hr>
|
|
130
|
-
<div id="section-arp-cache" class="form-group mt-2 div-hide">
|
|
131
|
-
<h6>Device Detection <span class=text-color>/</span> ARP Cache Settings</h6>
|
|
132
|
-
<div class="row">
|
|
133
|
-
<div class="col">
|
|
134
|
-
<label for="arp_cache_attempts" class="form-label">Attempts</label>
|
|
135
|
-
<input type="number" id="arp_cache_attempts" class="form-control">
|
|
136
|
-
</div>
|
|
137
|
-
<div class="col">
|
|
138
|
-
<label for="arp_cache_wait_before" class="form-label">Wait Before (sec)</label>
|
|
139
|
-
<input type="number" step="0.1" id="arp_cache_wait_before" class="form-control">
|
|
140
|
-
</div>
|
|
141
|
-
</div>
|
|
142
|
-
</div>
|
|
143
|
-
|
|
144
|
-
<hr>
|
|
145
|
-
<div id="section-poke" class="form-group mt-2 div-hide">
|
|
146
|
-
<h6>Device Detection <span class=text-color>/</span> Poke Settings</h6>
|
|
147
|
-
<div class="row">
|
|
148
|
-
<div class="col">
|
|
149
|
-
<label for="poke_attempts" class="form-label">Attempts</label>
|
|
150
|
-
<input type="number" id="poke_attempts" class="form-control">
|
|
151
|
-
</div>
|
|
152
|
-
<div class="col">
|
|
153
|
-
<label for="poke_timeout" class="form-label">Timeout (sec)</label>
|
|
154
|
-
<input type="number" step="0.1" id="poke_timeout" class="form-control">
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
|
|
159
|
-
<hr>
|
|
160
|
-
|
|
161
|
-
<div class="form-group mt-2">
|
|
162
|
-
<h6>Port Testing</h6>
|
|
163
|
-
<div class="row">
|
|
164
|
-
<div class="col-3">
|
|
165
|
-
<label for="t_cnt_port_scan">Device Scan Threads</label>
|
|
166
|
-
<input type="number" id="t_cnt_port_scan" class="form-control">
|
|
167
|
-
</div>
|
|
168
|
-
<div class="col-1 descriptor">X</div>
|
|
169
|
-
<div class="col-3">
|
|
170
|
-
<label for="t_cnt_port_test">Port Test Threads</label>
|
|
171
|
-
<input type="number" id="t_cnt_port_test" class="form-control">
|
|
172
|
-
</div>
|
|
173
|
-
<div class="col-1 descriptor">=</div>
|
|
174
|
-
<div class="col-3">
|
|
175
|
-
<label for="total-port-tests">Total concurrent tests</label>
|
|
176
|
-
<input type="number" id="total-port-tests" class="form-control" readonly>
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
<div class="row mt-2">
|
|
180
|
-
<div class="col">
|
|
181
|
-
<label for="port_list">Port List</label>
|
|
182
|
-
<div class="port-list-wrapper">
|
|
183
|
-
<select id="port_list" class="port-list">
|
|
184
|
-
<option value="both">ARP + Ping</option>
|
|
185
|
-
<option value="arp">ARP Only</option>
|
|
186
|
-
<option value="ping">Ping Only</option>
|
|
187
|
-
</select>
|
|
188
|
-
</div>
|
|
189
|
-
</div>
|
|
190
|
-
</div>
|
|
191
|
-
<hr>
|
|
192
|
-
|
|
193
|
-
<div class="form-group mt-2">
|
|
194
|
-
<h6>Stages</h6>
|
|
195
|
-
<div class="form-check"
|
|
196
|
-
data-bs-toggle="tooltip"
|
|
197
|
-
data-bs-placement="right"
|
|
198
|
-
title="Find Devices using ARP or Ping (always on)"
|
|
199
|
-
>
|
|
200
|
-
<input class="form-check-input" disabled type="checkbox" id="task_find_devices" checked>
|
|
201
|
-
<label class="form-check-label" for="task_find_devices">Find Devices</label>
|
|
202
|
-
</div>
|
|
203
|
-
<div class="form-check"
|
|
204
|
-
data-bs-toggle="tooltip"
|
|
205
|
-
data-bs-placement="right"
|
|
206
|
-
title="Find open ports on devices"
|
|
207
|
-
>
|
|
208
|
-
<input class="form-check-input" type="checkbox" id="task_scan_ports">
|
|
209
|
-
<label class="form-check-label" for="task_scan_ports">Scan Ports</label>
|
|
210
|
-
</div>
|
|
211
|
-
<div class="form-check"
|
|
212
|
-
data-bs-toggle="tooltip"
|
|
213
|
-
data-bs-placement="right"
|
|
214
|
-
title="Determine services running on open ports (no supporting UI yet)"
|
|
215
|
-
>
|
|
216
|
-
<input class="form-check-input" type="checkbox" id="task_scan_port_services">
|
|
217
|
-
<label class="form-check-label" for="task_scan_port_services">Scan Port Services</label>
|
|
218
|
-
</div>
|
|
219
|
-
</div>
|
|
220
|
-
|
|
221
|
-
</div>
|
|
222
|
-
|
|
223
|
-
</div>
|
|
224
|
-
<div class="modal-footer border-secondary">
|
|
225
|
-
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|