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.

Files changed (87) hide show
  1. {lanscape-1.3.8b1/lanscape.egg-info → lanscape-1.4.0}/PKG-INFO +1 -1
  2. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/decorators.py +29 -3
  3. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/net_tools.py +10 -25
  4. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/version_manager.py +15 -18
  5. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/css/style.css +8 -0
  6. lanscape-1.4.0/lanscape/ui/templates/scan/config.html +221 -0
  7. {lanscape-1.3.8b1 → lanscape-1.4.0/lanscape.egg-info}/PKG-INFO +1 -1
  8. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape.egg-info/SOURCES.txt +1 -0
  9. {lanscape-1.3.8b1 → lanscape-1.4.0}/pyproject.toml +1 -1
  10. lanscape-1.4.0/tests/test_decorators.py +29 -0
  11. lanscape-1.3.8b1/lanscape/ui/templates/scan/config.html +0 -229
  12. {lanscape-1.3.8b1 → lanscape-1.4.0}/LICENSE +0 -0
  13. {lanscape-1.3.8b1 → lanscape-1.4.0}/MANIFEST.in +0 -0
  14. {lanscape-1.3.8b1 → lanscape-1.4.0}/README.md +0 -0
  15. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/__init__.py +0 -0
  16. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/__main__.py +0 -0
  17. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/__init__.py +0 -0
  18. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/app_scope.py +0 -0
  19. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/device_alive.py +0 -0
  20. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/errors.py +0 -0
  21. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/ip_parser.py +0 -0
  22. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/logger.py +0 -0
  23. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/mac_lookup.py +0 -0
  24. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/port_manager.py +0 -0
  25. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/runtime_args.py +0 -0
  26. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/scan_config.py +0 -0
  27. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/service_scan.py +0 -0
  28. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/subnet_scan.py +0 -0
  29. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/libraries/web_browser.py +0 -0
  30. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/mac_addresses/convert_csv.py +0 -0
  31. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/mac_addresses/mac_db.json +0 -0
  32. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/convert_csv.py +0 -0
  33. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/full.json +0 -0
  34. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/large.json +0 -0
  35. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/medium.json +0 -0
  36. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/ports/small.json +0 -0
  37. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/resources/services/definitions.jsonc +0 -0
  38. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/__init__.py +0 -0
  39. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/app.py +0 -0
  40. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/__init__.py +0 -0
  41. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/api/__init__.py +0 -0
  42. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/api/port.py +0 -0
  43. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/api/scan.py +0 -0
  44. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/api/tools.py +0 -0
  45. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/web/__init__.py +0 -0
  46. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/blueprints/web/routes.py +0 -0
  47. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/main.py +0 -0
  48. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/shutdown_handler.py +0 -0
  49. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/android-chrome-192x192.png +0 -0
  50. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/android-chrome-512x512.png +0 -0
  51. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/apple-touch-icon.png +0 -0
  52. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/favicon-16x16.png +0 -0
  53. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/favicon-32x32.png +0 -0
  54. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/favicon.ico +0 -0
  55. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/img/ico/site.webmanifest +0 -0
  56. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/core.js +0 -0
  57. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/layout-sizing.js +0 -0
  58. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/main.js +0 -0
  59. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/on-tab-close.js +0 -0
  60. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/quietReload.js +0 -0
  61. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/scan-config.js +0 -0
  62. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/shutdown-server.js +0 -0
  63. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/subnet-info.js +0 -0
  64. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/js/subnet-selector.js +0 -0
  65. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/static/lanscape.webmanifest +0 -0
  66. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/base.html +0 -0
  67. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/core/head.html +0 -0
  68. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/core/scripts.html +0 -0
  69. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/error.html +0 -0
  70. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/info.html +0 -0
  71. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/main.html +0 -0
  72. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/export.html +0 -0
  73. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/ip-table-row.html +0 -0
  74. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/ip-table.html +0 -0
  75. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/overview.html +0 -0
  76. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan/scan-error.html +0 -0
  77. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/scan.html +0 -0
  78. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape/ui/templates/shutdown.html +0 -0
  79. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape.egg-info/dependency_links.txt +0 -0
  80. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape.egg-info/requires.txt +0 -0
  81. {lanscape-1.3.8b1 → lanscape-1.4.0}/lanscape.egg-info/top_level.txt +0 -0
  82. {lanscape-1.3.8b1 → lanscape-1.4.0}/setup.cfg +0 -0
  83. {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_api.py +0 -0
  84. {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_env.py +0 -0
  85. {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_library.py +0 -0
  86. {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_logging.py +0 -0
  87. {lanscape-1.3.8b1 → lanscape-1.4.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lanscape
3
- Version: 1.3.8b1
3
+ Version: 1.4.0
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  License-Expression: MIT
@@ -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
- class ArpSupportChecker:
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
- return ArpSupportChecker.is_supported()
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
- global LATEST_VERSION # pylint: disable=global-statement
66
- if not LATEST_VERSION:
67
- no_cache = f'?cachebust={randint(0, 6969)}'
68
- url = f"https://pypi.org/pypi/{package}/json{no_cache}"
69
- try:
70
- response = requests.get(url, timeout=5)
71
- response.raise_for_status() # Raise an exception for HTTP errors
72
- LATEST_VERSION = response.json()['info']['version']
73
- log.debug(f'Latest pypi version: {LATEST_VERSION}')
74
- except BaseException:
75
- log.debug(traceback.format_exc())
76
- log.warning('Unable to fetch package version from PyPi')
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>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lanscape
3
- Version: 1.3.8b1
3
+ Version: 1.4.0
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  License-Expression: MIT
@@ -77,6 +77,7 @@ lanscape/ui/templates/scan/ip-table.html
77
77
  lanscape/ui/templates/scan/overview.html
78
78
  lanscape/ui/templates/scan/scan-error.html
79
79
  tests/test_api.py
80
+ tests/test_decorators.py
80
81
  tests/test_env.py
81
82
  tests/test_library.py
82
83
  tests/test_logging.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lanscape"
3
- version = "1.3.8b1"
3
+ version = "1.4.0"
4
4
  authors = [
5
5
  { name="Michael Dennis", email="michael@dipduo.com" },
6
6
  ]
@@ -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