lanscape 2.0.2a4__py3-none-any.whl → 2.1.2__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.
@@ -12,8 +12,9 @@ import psutil
12
12
  from scapy.sendrecv import srp
13
13
  from scapy.layers.l2 import ARP, Ether
14
14
  from icmplib import ping
15
+ from icmplib.exceptions import SocketPermissionError
15
16
 
16
- from lanscape.core.net_tools import Device
17
+ from lanscape.core.net_tools import Device, DeviceError
17
18
  from lanscape.core.scan_config import (
18
19
  ScanConfig, ScanType, PingConfig,
19
20
  ArpConfig, PokeConfig, ArpCacheConfig
@@ -72,18 +73,84 @@ class IcmpLookup():
72
73
  Returns:
73
74
  bool: True if the device is reachable via ICMP, False otherwise.
74
75
  """
75
- # Perform up to cfg.attempts rounds of ping(count=cfg.ping_count)
76
- for _ in range(cfg.attempts):
77
- result = ping(
78
- device.ip,
79
- count=cfg.ping_count,
80
- interval=cfg.retry_delay,
81
- timeout=cfg.timeout,
82
- privileged=psutil.WINDOWS # Use privileged mode on Windows
83
- )
84
- if result.is_alive:
85
- device.alive = True
86
- break
76
+ try:
77
+ # Try using icmplib first
78
+ for _ in range(cfg.attempts):
79
+ result = ping(
80
+ device.ip,
81
+ count=cfg.ping_count,
82
+ interval=cfg.retry_delay,
83
+ timeout=cfg.timeout,
84
+ privileged=psutil.WINDOWS # Use privileged mode on Windows
85
+ )
86
+ if result.is_alive:
87
+ device.alive = True
88
+ break
89
+ return device.alive is True
90
+ except SocketPermissionError:
91
+ # Fallback to system ping command when raw sockets aren't available
92
+ return cls._ping_fallback(device, cfg)
93
+
94
+ @classmethod
95
+ def _ping_fallback(cls, device: Device, cfg: PingConfig) -> bool:
96
+ """Fallback ping using system ping command via subprocess.
97
+
98
+ Args:
99
+ device (Device): The device to ping.
100
+ cfg (PingConfig): The ping configuration.
101
+
102
+ Returns:
103
+ bool: True if the device responds to ping, False otherwise.
104
+ """
105
+ cmd = []
106
+
107
+ if psutil.WINDOWS:
108
+ # -n count, -w timeout in ms
109
+ cmd = ['ping', '-n', str(cfg.ping_count), '-w', str(int(cfg.timeout * 1000)), device.ip]
110
+ else: # Linux, macOS, and other Unix-like systems
111
+ # -c count, -W timeout in s
112
+ cmd = ['ping', '-c', str(cfg.ping_count), '-W', str(int(cfg.timeout)), device.ip]
113
+
114
+ for r in range(cfg.attempts):
115
+ try:
116
+ # Remove check=True to handle return codes manually
117
+ # Add timeout to prevent hanging
118
+ timeout_val = cfg.timeout * cfg.ping_count + 5
119
+ proc = subprocess.run(
120
+ cmd,
121
+ text=True,
122
+ stdout=subprocess.PIPE,
123
+ stderr=subprocess.PIPE,
124
+ timeout=timeout_val,
125
+ check=False # Handle return codes manually
126
+ )
127
+
128
+ # Check if ping was successful
129
+ if proc.returncode == 0:
130
+ output = proc.stdout.lower()
131
+
132
+ # Windows/Linux both include "TTL" on a successful reply
133
+ if psutil.WINDOWS or psutil.LINUX:
134
+ if 'ttl' in output:
135
+ device.alive = True
136
+ return True # Early return on success
137
+
138
+ # some distributions of Linux and macOS
139
+ if psutil.MACOS or psutil.LINUX:
140
+ bad = '100.0% packet loss'
141
+ good = 'ping statistics'
142
+ # mac doesnt include TTL, so we check good is there, and bad is not
143
+ if good in output and bad not in output:
144
+ device.alive = True
145
+ return True # Early return on success
146
+
147
+ except (subprocess.CalledProcessError, subprocess.TimeoutExpired,
148
+ FileNotFoundError) as e:
149
+ device.caught_errors.append(DeviceError(e))
150
+
151
+ if r < cfg.attempts - 1:
152
+ time.sleep(cfg.retry_delay)
153
+
87
154
  return device.alive is True
88
155
 
89
156
 
@@ -31,10 +31,10 @@ else:
31
31
 
32
32
  from lanscape.core.service_scan import scan_service
33
33
  from lanscape.core.mac_lookup import MacLookup, get_macs
34
- from lanscape.core.ip_parser import get_address_count, MAX_IPS_ALLOWED
34
+ from lanscape.core.ip_parser import get_address_count, MAX_IPS_ALLOWED, parse_ip_input
35
35
  from lanscape.core.errors import DeviceError
36
36
  from lanscape.core.decorators import job_tracker, run_once, timeout_enforcer
37
- from lanscape.core.scan_config import ServiceScanConfig, PortScanConfig
37
+ from lanscape.core.scan_config import ServiceScanConfig, PortScanConfig, ScanType
38
38
 
39
39
  log = logging.getLogger('NetTools')
40
40
  mac_lookup = MacLookup()
@@ -552,6 +552,56 @@ def smart_select_primary_subnet(subnets: List[dict] = None) -> str:
552
552
  return selected.get("subnet", "")
553
553
 
554
554
 
555
+ def is_internal_block(subnet: str) -> bool:
556
+ """
557
+ Check if a subnet contains only internal/private IP addresses.
558
+
559
+ Supports CIDR notation, IP ranges, comma-separated lists, and single IPs.
560
+ For ranges and complex inputs, samples representative IPs for efficiency.
561
+
562
+ Args:
563
+ subnet: IP subnet string in various formats
564
+
565
+ Returns:
566
+ bool: True if all sampled IPs are private/internal, False otherwise
567
+ """
568
+ try:
569
+ # Handle comma-separated subnets recursively
570
+ if ',' in subnet:
571
+ return all(is_internal_block(part.strip()) for part in subnet.split(','))
572
+
573
+ # Handle CIDR notation directly
574
+ if '/' in subnet:
575
+ return ipaddress.IPv4Network(subnet, strict=False).is_private
576
+
577
+ # Handle ranges and single IPs by parsing and sampling
578
+ ip_list = parse_ip_input(subnet)
579
+ sample_ips = ([ip_list[0], ip_list[-1]] if len(ip_list) > 1 else ip_list)
580
+ return all(ipaddress.IPv4Address(ip).is_private for ip in sample_ips)
581
+
582
+ except (ValueError, ipaddress.AddressValueError):
583
+ return False # Assume external for unparseable input
584
+
585
+
586
+ def scan_config_uses_arp(config) -> bool:
587
+ """
588
+ Check if a scan configuration uses ARP-based scanning methods.
589
+
590
+ Args:
591
+ config: ScanConfig instance
592
+
593
+ Returns:
594
+ bool: True if the configuration uses ARP scanning, False otherwise
595
+ """
596
+ arp_scan_types = {
597
+ ScanType.ARP_LOOKUP,
598
+ ScanType.POKE_THEN_ARP,
599
+ ScanType.ICMP_THEN_ARP
600
+ }
601
+
602
+ return any(scan_type in arp_scan_types for scan_type in config.lookup_type)
603
+
604
+
555
605
  @run_once
556
606
  def is_arp_supported():
557
607
  """
@@ -22,7 +22,9 @@ from tabulate import tabulate
22
22
  # Local imports
23
23
  from lanscape.core.scan_config import ScanConfig
24
24
  from lanscape.core.decorators import job_tracker, terminator, JobStats
25
- from lanscape.core.net_tools import Device
25
+ from lanscape.core.net_tools import (
26
+ Device, is_internal_block, scan_config_uses_arp
27
+ )
26
28
  from lanscape.core.errors import SubnetScanTerminationFailure
27
29
  from lanscape.core.device_alive import is_device_alive
28
30
 
@@ -301,11 +303,11 @@ class ScannerResults:
301
303
  Calculate the runtime of the scan in seconds.
302
304
 
303
305
  Returns:
304
- int: Runtime in seconds
306
+ float: Runtime in seconds
305
307
  """
306
308
  if self.scan.running:
307
- return int(time() - self.start_time)
308
- return int(self.end_time - self.start_time)
309
+ return time() - self.start_time
310
+ return self.end_time - self.start_time
309
311
 
310
312
  def export(self, out_type=dict) -> Union[str, dict]:
311
313
  """
@@ -385,6 +387,13 @@ class ScanManager:
385
387
  Returns:
386
388
  SubnetScanner: The newly created scan instance
387
389
  """
390
+ if not is_internal_block(config.subnet) and scan_config_uses_arp(config):
391
+ self.log.warning(
392
+ f"ARP scanning detected for external subnet '{config.subnet}'. "
393
+ "ARP requests typically only work within the local network segment. "
394
+ "Consider using ICMP scanning for external IP ranges."
395
+ )
396
+
388
397
  scan = SubnetScanner(config)
389
398
  self._start(scan)
390
399
  self.log.info(f'Scan started - {config}')
@@ -8,7 +8,7 @@ from flask import request
8
8
  from lanscape.core.runtime_args import parse_args
9
9
 
10
10
 
11
- log = logging.getLogger('shutdown_handler')
11
+ log = logging.getLogger('ShutdownHandler')
12
12
 
13
13
 
14
14
  class FlaskShutdownHandler:
@@ -34,6 +34,9 @@
34
34
  --danger-border-color: #922; /* Bold red for danger borders */
35
35
 
36
36
  --footer-height: 25px;
37
+
38
+ --fa-primary-color: var(--text-accent-color);
39
+ --fa-secondary-color: var(--text-placeholder);
37
40
  }
38
41
 
39
42
  body {
@@ -244,7 +247,7 @@ details {
244
247
  transition: all .5s ease-in-out
245
248
  }
246
249
 
247
- #app-actions a .material-symbols-outlined {
250
+ #app-actions a .fa-solid {
248
251
  font-size: inherit
249
252
  }
250
253
  #app-actions {
@@ -257,9 +260,12 @@ details {
257
260
  color: var(--text-color);
258
261
  text-decoration: none;
259
262
  cursor: pointer;
263
+ --fa-primary-color: var(--text-accent-color);
264
+ --fa-secondary-color: var(--text-placeholder);
260
265
  }
261
- #app-actions a:hover {
262
- color: var(--text-placeholder)
266
+ #app-actions a i:hover {
267
+ --fa-primary-color: var(--text-color);
268
+ --fa-secondary-color: var(--text-accent-color);
263
269
  }
264
270
 
265
271
  #power-button {
@@ -274,10 +280,10 @@ details {
274
280
  display: flex;
275
281
  justify-content: space-around;
276
282
  align-items: center;
277
- a {
278
- text-decoration: none;
279
- margin: 0 3px;
280
- }
283
+ }
284
+
285
+ #scan-actions i {
286
+ font-size: 20px;
281
287
  }
282
288
 
283
289
  #advanced-modal {
@@ -796,13 +802,7 @@ html {
796
802
  }
797
803
 
798
804
 
799
- .material-symbols-outlined {
800
- font-variation-settings:
801
- 'FILL' 0,
802
- 'wght' 400,
803
- 'GRAD' 0,
804
- 'opsz' 24
805
- }
805
+ /* FontAwesome Solid Icon Styling */
806
806
 
807
807
  #shutdown-sub-sub {
808
808
  color: var(--text-almost-hidden);
@@ -942,7 +942,7 @@ html {
942
942
  border-radius: 999px;
943
943
  color: var(--text-color);
944
944
  }
945
- #device-modal .chip .material-symbols-outlined {
945
+ #device-modal .chip .fa-solid {
946
946
  font-size: 16px;
947
947
  }
948
948
 
@@ -24,24 +24,22 @@
24
24
 
25
25
  <div id="app-actions">
26
26
  <a href="/info">
27
- <span
28
- class="material-symbols-outlined"
27
+ <i
28
+ class="fa-duotone fa-light fa-circle-info"
29
29
  data-bs-toggle="tooltip"
30
30
  data-bs-placement="top"
31
31
  title="App info">
32
- info
33
- </span>
32
+ </i>
34
33
  </a>
35
34
 
36
35
  <a href="/shutdown-ui">
37
- <span
36
+ <i
38
37
  id="power-button"
39
- class="material-symbols-outlined"
38
+ class="fa-solid fa-power-off"
40
39
  data-bs-toggle="tooltip"
41
40
  data-bs-placement="top"
42
41
  title="Shutdown App">
43
- power_settings_new
44
- </span>
42
+ </i>
45
43
  </a>
46
44
  </div>
47
45
 
@@ -3,7 +3,7 @@
3
3
  <title>LANscape</title>
4
4
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
5
5
  <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
6
- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
6
+ <script src="https://kit.fontawesome.com/d0b7f59243.js" crossorigin="anonymous"></script>
7
7
  <link rel="apple-touch-icon" sizes="180x180" href="/static/img/ico/apple-touch-icon.png">
8
8
  <link rel="icon" type="image/png" sizes="32x32" href="/static/img/ico/favicon-32x32.png">
9
9
  <link rel="icon" type="image/png" sizes="16x16" href="/static/img/ico/favicon-16x16.png">
@@ -14,7 +14,10 @@
14
14
  <div class="scroll-container" id="content">
15
15
  {% if update_available %}
16
16
  <div class="container-fluid my-4">
17
- <h3>New version available!</h3>
17
+ <h3>
18
+ <i class="fa-solid fa-cloud-arrow-up"></i>
19
+ New version available!
20
+ </h3>
18
21
  <p>
19
22
  A new version has been published to PyPi.
20
23
  ({{app_version}} -> {{latest_version}})
@@ -26,7 +29,10 @@
26
29
  </div>
27
30
  {% endif %}
28
31
  <div class="container-fluid my-4">
29
- <h3>About</h3>
32
+ <h3>
33
+ <i class="fa-duotone fa-light fa-circle-question"></i>
34
+ About
35
+ </h3>
30
36
  <p>
31
37
  LANscape was born from my frustration with existing local network scanning tools
32
38
  alongside my desire to dive deeper into technologies like
@@ -36,14 +42,23 @@
36
42
  discover more about your network as well. Enjoy!
37
43
  </p>
38
44
  <a href="https://github.com/mdennis281/" class="text-decoration-none" target="_blank">
39
- <button class="btn btn-primary m-2">GitHub</button>
45
+ <button class="btn btn-primary m-2">
46
+ <i class="fa-brands fa-github"></i>
47
+ GitHub
48
+ </button>
40
49
  </a>
41
50
  <a href="https://github.com/mdennis281/LANscape" class="text-decoration-none" target="_blank">
42
- <button class="btn btn-secondary m-2">Project Repo</button>
51
+ <button class="btn btn-secondary m-2">
52
+ <i class="fa-solid fa-code-fork"></i>
53
+ Project Repo
54
+ </button>
43
55
  </a>
44
56
  </div>
45
57
  <div class="container-fluid my-4">
46
- <h3>Runtime Arguments</h3>
58
+ <h3>
59
+ <i class="fa-duotone fa-light fa-sliders"></i>
60
+ Runtime Arguments
61
+ </h3>
47
62
  <table class="table table-striped table-bordered">
48
63
  <thead class="table-dark">
49
64
  <tr>
@@ -23,12 +23,12 @@
23
23
  <button
24
24
  type="button"
25
25
  id="settings-btn"
26
- class="btn btn-secondary start material-symbols-outlined"
26
+ class="btn btn-secondary start"
27
27
  data-bs-toggle="tooltip"
28
28
  data-bs-placement="bottom"
29
29
  title="Advanced scan settings"
30
30
  >
31
- settings
31
+ <i class="fa-solid fa-gear"></i>
32
32
  </button>
33
33
  <input type="text" id="subnet" name="subnet" class="form-control" value="{{ subnet }}" placeholder="Enter subnet">
34
34
  <button class="btn btn-secondary dropdown-toggle end" type="button" id="subnet-dropdown" data-bs-toggle="dropdown" aria-expanded="false"></button>
@@ -59,13 +59,12 @@
59
59
  <h2>Scan Results</h2>
60
60
  <div id="scan-actions">
61
61
  <a href="" id="export-link">
62
- <span
63
- class="material-symbols-outlined secondary-icon-btn"
62
+ <i
63
+ class="fa-solid fa-upload secondary-icon-btn"
64
64
  data-bs-toggle="tooltip"
65
65
  data-bs-placement="top"
66
66
  title="Export scan to json">
67
- ios_share
68
- </span>
67
+ </i>
69
68
  </a>
70
69
  </div>
71
70
  </div>
@@ -8,21 +8,24 @@
8
8
  <div class="modal-body">
9
9
  <div class="d-flex gap-2 mb-3">
10
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>
11
+ <div class="d-flex flex-column align-items-center justify-content-center">
12
+ <i class="fa-solid fa-bolt mb-2" style="font-size: 1.5em;"></i>
13
+ <h5 class="mb-1">Fast</h5>
14
+ </div>
14
15
  <p class="mb-0">Fast scan, Low accuracy</p>
15
16
  </div>
16
17
  <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>
18
+ <div class="d-flex flex-column align-items-center justify-content-center">
19
+ <i class="fa-solid fa-scale-balanced mb-2" style="font-size: 1.5em;"></i>
20
+ <h5 class="mb-1">Balanced</h5>
21
+ </div>
20
22
  <p class="mb-0">Balanced scan, Moderate accuracy</p>
21
23
  </div>
22
24
  <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>
25
+ <div class="d-flex flex-column align-items-center justify-content-center">
26
+ <i class="fa-solid fa-bullseye mb-2" style="font-size: 1.5em;"></i>
27
+ <h5 class="mb-1">Accurate</h5>
28
+ </div>
26
29
  <p class="mb-0">Thorough scan, High accuracy</p>
27
30
  </div>
28
31
  </div>
@@ -51,15 +54,13 @@
51
54
  ARP Lookup
52
55
  </label>
53
56
  {% if not is_arp_supported %}
54
- <span
55
- class="material-symbols-outlined arp-help-ico"
57
+ <i
58
+ class="fa-solid fa-circle-question arp-help-ico"
56
59
  data-bs-toggle="tooltip"
57
60
  data-bs-placement="top"
58
61
  title="ARP lookup is not supported on this system, click for more info"
59
62
  onclick="window.open('https://github.com/mdennis281/LANscape/blob/main/docs/arp-issues.md', '_blank')"
60
- >
61
- help
62
- </span>
63
+ ></i>
63
64
  {% endif %}
64
65
  </div>
65
66
  <div class="form-check">
@@ -49,7 +49,7 @@
49
49
  <div class="chip-group mt-1">
50
50
  {% for p in ports %}
51
51
  <span class="chip" title="Port {{ p }}">
52
- <span class="material-symbols-outlined">lan</span>{{ p }}
52
+ <i class="fa-solid fa-network-wired"></i>{{ p }}
53
53
  </span>
54
54
  {% endfor %}
55
55
  </div>
@@ -65,7 +65,7 @@
65
65
  {% for svc, svc_ports in services|dictsort %}
66
66
  <div class="service-row">
67
67
  <div class="service-name">
68
- <span class="material-symbols-outlined align-middle me-1">dns</span>{{ svc|default('Unknown') }}
68
+ <i class="fa-solid fa-server align-middle me-1"></i>{{ svc|default('Unknown') }}
69
69
  </div>
70
70
  <div class="service-ports">
71
71
  {% set s_ports = svc_ports|default([]) %}
@@ -91,7 +91,7 @@
91
91
  <ul class="list-unstyled error-list mt-1">
92
92
  {% for err in errors %}
93
93
  <li class="text-danger">
94
- <span class="material-symbols-outlined align-middle me-1">error</span>
94
+ <i class="fa-solid fa-circle-exclamation align-middle me-1"></i>
95
95
  {{ err }}
96
96
  </li>
97
97
  {% endfor %}
@@ -1,10 +1,10 @@
1
1
  <tr>
2
2
  <td>
3
3
  <div class="info-icon-container">
4
- <span
5
- class="material-symbols-outlined info-icon"
4
+ <i
5
+ class="fa-solid fa-circle-info info-icon"
6
6
  onclick="parent.openDeviceDetail('{{ device.ip }}')"
7
- >info</span>
7
+ ></i>
8
8
  </div>
9
9
  </td>
10
10
  <td>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lanscape
3
- Version: 2.0.2a4
3
+ Version: 2.1.2
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  License-Expression: MIT
@@ -28,6 +28,8 @@ Requires-Dist: icmplib
28
28
  Provides-Extra: dev
29
29
  Requires-Dist: pytest>=8.0; extra == "dev"
30
30
  Requires-Dist: pytest-cov>=5.0; extra == "dev"
31
+ Requires-Dist: pytest-xdist>=3.0; extra == "dev"
32
+ Requires-Dist: openai>=1.0.0; extra == "dev"
31
33
  Dynamic: license-file
32
34
 
33
35
  # LANscape
@@ -3,17 +3,17 @@ lanscape/__main__.py,sha256=PuY42yuCLAwHrOREJ6u2DgVyGX5hZKRQeoE9pajkNfM,170
3
3
  lanscape/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  lanscape/core/app_scope.py,sha256=qfzX8Ed4bFdxHMGjgnLlWuLZDTCBKObermz91KbGVn0,3298
5
5
  lanscape/core/decorators.py,sha256=CZbPEfnLS1OF-uejQweetadzqf0pVo736jKko4Xs-g4,7264
6
- lanscape/core/device_alive.py,sha256=TC6c5uR-2xwT8IXcRA3NAPJ9iPhdVx9a42bGSKq9N6w,6833
6
+ lanscape/core/device_alive.py,sha256=VY2dsoy6_MWUxcysZEFcsSoCtDkLMYzwqy0U_sbVWE0,9609
7
7
  lanscape/core/errors.py,sha256=QTf42UzR9Zxj1t1mdwfLvZIp0c9a5EItELOdCR7kTmE,1322
8
8
  lanscape/core/ip_parser.py,sha256=kn5H4ERitLnreRAqifWphwbxdjItGqwu50lsMCPDMcA,3474
9
9
  lanscape/core/logger.py,sha256=nzo6J8UdlMdhRkOJEDOIHKztoE3Du8PQZad7ixvNgeM,2534
10
10
  lanscape/core/mac_lookup.py,sha256=PxBSMe3wEVDtivCsh5NclSAguZz9rqdAS7QshBiuWvM,3519
11
- lanscape/core/net_tools.py,sha256=W-yyQ05k6BJc8VOnOi9_hpVD2G8i5HuQ_A39O8qk30Y,19676
11
+ lanscape/core/net_tools.py,sha256=Ht8TkLnKf-f6E1_AkTCde-yuiwUNI57TCXke0nIFi0o,21303
12
12
  lanscape/core/port_manager.py,sha256=3_ROOb6JEiB0NByZVtADuGcldFkgZwn1RKtvwgs9AIk,4479
13
13
  lanscape/core/runtime_args.py,sha256=2vIqRrcWr-NHRSBlZGrxh1PdkPY0ytkPguu8KZqy2L8,2543
14
14
  lanscape/core/scan_config.py,sha256=A2ZKXqXKW9nrP6yLb7b9b3XqSY_cQB3LZ5K0LVCSebE,11114
15
15
  lanscape/core/service_scan.py,sha256=wTDxOdazOsbI0hwCBR__4UCmB2RIbl2pw3F2YUW9aaE,6428
16
- lanscape/core/subnet_scan.py,sha256=IegcrpzevL2zMf1fuvCqegUGCBXtO3iAI49aCweXmvw,14444
16
+ lanscape/core/subnet_scan.py,sha256=PtSOk92dK05-reyr8LBkOXaI15qpYnar5nDqALCX1tQ,14850
17
17
  lanscape/core/version_manager.py,sha256=eGjyKgsv31QO0W26se9pPQ1TwmEN8qn37dHULtoocqc,2841
18
18
  lanscape/core/web_browser.py,sha256=23MuGIrBYdGhw6ejj6OWxwReeKIlWhtWukc1dKV_3_0,6736
19
19
  lanscape/resources/mac_addresses/convert_csv.py,sha256=hvlyLs0XmuuhBuvXBNRGP1cKJzYVRSf8VfUJ1VqROms,1189
@@ -28,7 +28,7 @@ lanscape/resources/services/definitions.jsonc,sha256=M9BDeK-mh25sEVj8xDEYbU2ix7E
28
28
  lanscape/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  lanscape/ui/app.py,sha256=rg4UGHgbVHpU2jdabSwBoSqGna7WGOunPkPc5Tvds9w,4076
30
30
  lanscape/ui/main.py,sha256=UCrhHnyFBqVmHTMus33CTp3vdNn3miT1xXJatR4N7ho,4176
31
- lanscape/ui/shutdown_handler.py,sha256=He2aYlcfHvQjpJuKbdbjmUd2RkJeCrcSSHX9HFMbBOg,1705
31
+ lanscape/ui/shutdown_handler.py,sha256=HrEnWrdYSzLDVsPgD8tf9FgtAwQrZNECDu6wnEs27EY,1704
32
32
  lanscape/ui/blueprints/__init__.py,sha256=EjPtaR5Nh17pGiOVYTJULVNaZntpFZOiYyep8rBWAiE,265
33
33
  lanscape/ui/blueprints/api/__init__.py,sha256=5Z4Y7B36O-bNFenpomfuNhPuJ9dW_MC0TPUU3pCFVfA,103
34
34
  lanscape/ui/blueprints/api/port.py,sha256=KlfLrAmlTqN44I1jLVDy-mWOcor4kL-b0Cl4AcTMCys,1976
@@ -37,7 +37,7 @@ lanscape/ui/blueprints/api/tools.py,sha256=jr9gt0VhvBFgJ61MLgNIM6hin-MUmJLGdmStP
37
37
  lanscape/ui/blueprints/web/__init__.py,sha256=NvgnjP0X4LwqVhSEyh5RUzoG45N44kHK1MEFlfvBxTg,118
38
38
  lanscape/ui/blueprints/web/routes.py,sha256=f5TzfTzelJ_erslyBXTOpFr4BlIfB1Mb1ye6ioH7IL0,4534
39
39
  lanscape/ui/static/lanscape.webmanifest,sha256=07CqA-PQsO35KJD8R96sI3Pxix6UuBjijPDCuy9vM3s,446
40
- lanscape/ui/static/css/style.css,sha256=qXDshNhj77__06AuL-RhsxlrqZ5S0JFAmy3M1sk1Sm8,21098
40
+ lanscape/ui/static/css/style.css,sha256=9IQru_W0WUpcxNJuHbqwjfxLOC5n1EeGcxf_kDVY3jc,21232
41
41
  lanscape/ui/static/img/ico/android-chrome-192x192.png,sha256=JmFT6KBCCuoyxMV-mLNtF9_QJbVBvfWPUizKN700fi8,18255
42
42
  lanscape/ui/static/img/ico/android-chrome-512x512.png,sha256=88Jjx_1-4XAnZYz64KP6FdTl_kYkNG2_kQIKteQwSh4,138055
43
43
  lanscape/ui/static/img/ico/apple-touch-icon.png,sha256=tEJlLwBZtF4v-NC90YCfRJQ2prTsF4i3VQLK_hnv2Mw,16523
@@ -54,24 +54,24 @@ lanscape/ui/static/js/scan-config.js,sha256=TiUwWWUGqqQbC3ZJnQCNQpoR492RXA3jLkAL
54
54
  lanscape/ui/static/js/shutdown-server.js,sha256=Mx8UGmmktHaCK7DL8TVUxah6VEcN0wwLFfhbCId-K8U,453
55
55
  lanscape/ui/static/js/subnet-info.js,sha256=osZM6CGs-TC5QpBJWkNWCtXNOKzjyIiWKHwKi4vlDf8,559
56
56
  lanscape/ui/static/js/subnet-selector.js,sha256=2YKCAuKU2Ti1CmJrqi4_vNTD2LQbxx7chIDqND_1eAY,358
57
- lanscape/ui/templates/base.html,sha256=cnKU-kHUBpt6Xg4gPLE4dWkcXr3H-K4Vz1Im8xDKdOQ,1448
57
+ lanscape/ui/templates/base.html,sha256=HIHLFEUMDTGEaeuSpeNg-vkXXb9VNbZnbFWlYetVL18,1377
58
58
  lanscape/ui/templates/error.html,sha256=bqGJbf_ix9wtpUlXk5zvz_XyFpeTbEO-4f0ImgLtUGk,1033
59
- lanscape/ui/templates/info.html,sha256=gu8SGFUaFQc46Rm4TkZD8HM4Tnls-ZWsJ0FJNhx9wEs,2545
60
- lanscape/ui/templates/main.html,sha256=ubxKUQcWQ27A0YpvBgj6AnIqgVSfW3exYXyn7EgrKJM,3895
59
+ lanscape/ui/templates/info.html,sha256=SQ6RpTs9_v9HF32mr3FBsh6vTJneYqFz_WrC9diXzHg,2958
60
+ lanscape/ui/templates/main.html,sha256=jTFLH9xuMNayQRkDNB_8BIQopaD4YtI5MI2zMpaMsMA,3842
61
61
  lanscape/ui/templates/scan.html,sha256=00QX2_1S_1wGzk42r00LjEkJvoioCLs6JgjOibi6r20,376
62
62
  lanscape/ui/templates/shutdown.html,sha256=iXVCq2yl5TjZfNFl4esbDJra3gJA2VQpae0jj4ipy9w,701
63
- lanscape/ui/templates/core/head.html,sha256=eZiebt24xYd_NALe-fFL25rb4uFjUrF4XJjxFH61MgM,779
63
+ lanscape/ui/templates/core/head.html,sha256=zP1RkTYuaKCC6RtnSEHFKPw3wKWfSyV0HZg5XsAxWik,719
64
64
  lanscape/ui/templates/core/scripts.html,sha256=rSRi4Ut8iejajMPhOc5bzEz-Z3EHxpj_3PxwwyyhmTQ,640
65
- lanscape/ui/templates/scan/config.html,sha256=nmk7Vn-9sXrTDJxSSR7JbCUJEVVadXSMji7LJv2tzKQ,14604
66
- lanscape/ui/templates/scan/device-detail.html,sha256=Yo4t4S5tkOboMQ3b0y-dHlTJIp6_Zb--9iopyQjNMSc,4825
65
+ lanscape/ui/templates/scan/config.html,sha256=X95xayNtJrRUeGUlPbtUjd1228hH6re9BT6jcbaSnl8,14704
66
+ lanscape/ui/templates/scan/device-detail.html,sha256=3N0WcdnWopbSFwsnKogBaHOYsLMAfKBZdkP7HQG4vLA,4794
67
67
  lanscape/ui/templates/scan/export.html,sha256=Nvs_unojzT3qhN_ZnEgYHou2C9wqWGr3dVr2UiLnYjY,749
68
- lanscape/ui/templates/scan/ip-table-row.html,sha256=nO5ZMhl3Gnlc8lg5nWmE05_6_5oz9ZfVCDUOgegVGpg,1267
68
+ lanscape/ui/templates/scan/ip-table-row.html,sha256=iSW3PYev3_k7pxTZUJUboqDUgdhsWNOrYxysYismyI0,1255
69
69
  lanscape/ui/templates/scan/ip-table.html,sha256=AT2ZvCPYdKl-XJiAkEAawPOVuQw-w0MXumGQTr3zyKM,926
70
70
  lanscape/ui/templates/scan/overview.html,sha256=xWj9jWDPg2KcPLvS8fnSins23_UXjKCdb2NJwNG2U2Q,1176
71
71
  lanscape/ui/templates/scan/scan-error.html,sha256=wmAYQ13IJHUoO8fAGNDjMvNml7tu4rsIU3Vav71ETlA,999
72
- lanscape-2.0.2a4.dist-info/licenses/LICENSE,sha256=VLoE0IrNTIc09dFm7hMN0qzk4T3q8V0NaPcFQqMemDs,1070
73
- lanscape-2.0.2a4.dist-info/METADATA,sha256=4gxey7gdxrvoYxVsMgsnaezruGtRS_5qen7Pp2zVFfQ,3486
74
- lanscape-2.0.2a4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
75
- lanscape-2.0.2a4.dist-info/entry_points.txt,sha256=evxSxUikFa1OEd4e0Boky9sLH87HdgM0YqB_AbB2HYc,51
76
- lanscape-2.0.2a4.dist-info/top_level.txt,sha256=E9D4sjPz_6H7c85Ycy_pOS2xuv1Wm-ilKhxEprln2ps,9
77
- lanscape-2.0.2a4.dist-info/RECORD,,
72
+ lanscape-2.1.2.dist-info/licenses/LICENSE,sha256=VLoE0IrNTIc09dFm7hMN0qzk4T3q8V0NaPcFQqMemDs,1070
73
+ lanscape-2.1.2.dist-info/METADATA,sha256=oxHxoHbAYnhTnSIgsMyzzgqevSrWmF5Fzti1bqjLAao,3578
74
+ lanscape-2.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
75
+ lanscape-2.1.2.dist-info/entry_points.txt,sha256=evxSxUikFa1OEd4e0Boky9sLH87HdgM0YqB_AbB2HYc,51
76
+ lanscape-2.1.2.dist-info/top_level.txt,sha256=E9D4sjPz_6H7c85Ycy_pOS2xuv1Wm-ilKhxEprln2ps,9
77
+ lanscape-2.1.2.dist-info/RECORD,,