lanscape 1.3.8a1__py3-none-any.whl → 2.4.0a2__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.

Potentially problematic release.


This version of lanscape might be problematic. Click here for more details.

Files changed (58) hide show
  1. lanscape/__init__.py +8 -4
  2. lanscape/{libraries → core}/app_scope.py +21 -3
  3. lanscape/core/decorators.py +231 -0
  4. lanscape/{libraries → core}/device_alive.py +83 -16
  5. lanscape/{libraries → core}/ip_parser.py +2 -26
  6. lanscape/{libraries → core}/net_tools.py +209 -66
  7. lanscape/{libraries → core}/runtime_args.py +6 -0
  8. lanscape/{libraries → core}/scan_config.py +103 -5
  9. lanscape/core/service_scan.py +222 -0
  10. lanscape/{libraries → core}/subnet_scan.py +30 -14
  11. lanscape/{libraries → core}/version_manager.py +15 -17
  12. lanscape/resources/ports/test_port_list_scan.json +4 -0
  13. lanscape/resources/services/definitions.jsonc +576 -400
  14. lanscape/ui/app.py +17 -5
  15. lanscape/ui/blueprints/__init__.py +1 -1
  16. lanscape/ui/blueprints/api/port.py +15 -1
  17. lanscape/ui/blueprints/api/scan.py +1 -1
  18. lanscape/ui/blueprints/api/tools.py +4 -4
  19. lanscape/ui/blueprints/web/routes.py +29 -2
  20. lanscape/ui/main.py +46 -19
  21. lanscape/ui/shutdown_handler.py +2 -2
  22. lanscape/ui/static/css/style.css +186 -20
  23. lanscape/ui/static/js/core.js +14 -0
  24. lanscape/ui/static/js/main.js +30 -2
  25. lanscape/ui/static/js/quietReload.js +3 -0
  26. lanscape/ui/static/js/scan-config.js +56 -6
  27. lanscape/ui/templates/base.html +6 -8
  28. lanscape/ui/templates/core/head.html +1 -1
  29. lanscape/ui/templates/info.html +20 -5
  30. lanscape/ui/templates/main.html +33 -36
  31. lanscape/ui/templates/scan/config.html +214 -176
  32. lanscape/ui/templates/scan/device-detail.html +111 -0
  33. lanscape/ui/templates/scan/ip-table-row.html +17 -83
  34. lanscape/ui/templates/scan/ip-table.html +5 -5
  35. lanscape/ui/ws/__init__.py +31 -0
  36. lanscape/ui/ws/delta.py +170 -0
  37. lanscape/ui/ws/handlers/__init__.py +20 -0
  38. lanscape/ui/ws/handlers/base.py +145 -0
  39. lanscape/ui/ws/handlers/port.py +184 -0
  40. lanscape/ui/ws/handlers/scan.py +352 -0
  41. lanscape/ui/ws/handlers/tools.py +145 -0
  42. lanscape/ui/ws/protocol.py +86 -0
  43. lanscape/ui/ws/server.py +375 -0
  44. {lanscape-1.3.8a1.dist-info → lanscape-2.4.0a2.dist-info}/METADATA +18 -3
  45. lanscape-2.4.0a2.dist-info/RECORD +85 -0
  46. {lanscape-1.3.8a1.dist-info → lanscape-2.4.0a2.dist-info}/WHEEL +1 -1
  47. lanscape-2.4.0a2.dist-info/entry_points.txt +2 -0
  48. lanscape/libraries/decorators.py +0 -170
  49. lanscape/libraries/service_scan.py +0 -50
  50. lanscape/libraries/web_browser.py +0 -210
  51. lanscape-1.3.8a1.dist-info/RECORD +0 -74
  52. /lanscape/{libraries → core}/__init__.py +0 -0
  53. /lanscape/{libraries → core}/errors.py +0 -0
  54. /lanscape/{libraries → core}/logger.py +0 -0
  55. /lanscape/{libraries → core}/mac_lookup.py +0 -0
  56. /lanscape/{libraries → core}/port_manager.py +0 -0
  57. {lanscape-1.3.8a1.dist-info → lanscape-2.4.0a2.dist-info}/licenses/LICENSE +0 -0
  58. {lanscape-1.3.8a1.dist-info → lanscape-2.4.0a2.dist-info}/top_level.txt +0 -0
@@ -13,6 +13,7 @@ $(document).ready(function() {
13
13
 
14
14
  $('#t_cnt_port_scan, #t_cnt_port_test').on('input', updatePortTotals);
15
15
  $('#ping_attempts, #ping_ping_count').on('input', updatePingTotals);
16
+ $('#task_scan_port_services').on('change', updateVisibility);
16
17
 
17
18
  // Lookup type toggles
18
19
  $('.lookup-type-input').on('change', onLookupTypeChanged);
@@ -43,6 +44,30 @@ function setScanConfig(configName) {
43
44
  $('#task_scan_ports').prop('checked', config.task_scan_ports);
44
45
  $('#task_scan_port_services').prop('checked', config.task_scan_port_services);
45
46
 
47
+ // port scan config
48
+ if (config.port_scan_config) {
49
+ $('#port_scan_timeout').val(config.port_scan_config.timeout);
50
+ $('#port_scan_retries').val(config.port_scan_config.retries);
51
+ $('#port_scan_retry_delay').val(config.port_scan_config.retry_delay);
52
+ } else {
53
+ // defaults if missing
54
+ $('#port_scan_timeout').val(1.0);
55
+ $('#port_scan_retries').val(0);
56
+ $('#port_scan_retry_delay').val(0.1);
57
+ }
58
+
59
+ // service config
60
+ if (config.service_scan_config) {
61
+ $('#service_lookup_type').val(config.service_scan_config.lookup_type || 'BASIC');
62
+ $('#service_timeout').val(config.service_scan_config.timeout);
63
+ $('#service_max_concurrent_probes').val(config.service_scan_config.max_concurrent_probes);
64
+ } else {
65
+ // defaults if missing
66
+ $('#service_lookup_type').val('BASIC');
67
+ $('#service_timeout').val(5.0);
68
+ $('#service_max_concurrent_probes').val(10);
69
+ }
70
+
46
71
  // lookup type (array of enum values as strings)
47
72
  setLookupTypeUI(config.lookup_type || []);
48
73
 
@@ -99,20 +124,41 @@ function getScanConfig() {
99
124
  poke_config: {
100
125
  attempts: parseInt($('#poke_attempts').val()),
101
126
  timeout: parseFloat($('#poke_timeout').val())
127
+ },
128
+ port_scan_config: {
129
+ timeout: parseFloat($('#port_scan_timeout').val()),
130
+ retries: parseInt($('#port_scan_retries').val()),
131
+ retry_delay: parseFloat($('#port_scan_retry_delay').val())
132
+ },
133
+ service_scan_config: {
134
+ timeout: parseFloat($('#service_timeout').val()),
135
+ lookup_type: $('#service_lookup_type').val(),
136
+ max_concurrent_probes: parseInt($('#service_max_concurrent_probes').val())
102
137
  }
103
138
  };
104
139
  }
105
140
 
106
141
  function getPortLists(callback=null) {
107
- $.get('/api/port/list', function(data) {
108
- const customSelectDropdown = $('#port_list');
142
+ const customSelectDropdown = $('#port_list');
143
+
144
+ const renderOptions = (items) => {
109
145
  customSelectDropdown.empty();
110
-
111
- // Populate the dropdown with the options
112
- data.forEach(function(portList) {
113
- customSelectDropdown.append('<option>' + portList + '</option>');
146
+ items.forEach((item) => {
147
+ const name = item.name || item;
148
+ const count = item.count;
149
+ const label = count !== undefined ? `${name} (${count} ports)` : name;
150
+ customSelectDropdown.append(`<option value="${name}">${label}</option>`);
114
151
  });
152
+ };
153
+
154
+ $.get('/api/port/list/summary', function(data) {
155
+ renderOptions(data || []);
115
156
  if (callback) callback();
157
+ }).fail(function() {
158
+ $.get('/api/port/list', function(data) {
159
+ renderOptions(data || []);
160
+ if (callback) callback();
161
+ });
116
162
  });
117
163
  }
118
164
 
@@ -168,6 +214,10 @@ function updateVisibility() {
168
214
  // Poke section only when POKE_THEN_ARP is selected
169
215
  const showPoke = types.has('POKE_THEN_ARP');
170
216
  toggleSection('#section-poke', showPoke);
217
+
218
+ // Service scan section visible only if stage enabled
219
+ const showService = $('#task_scan_port_services').is(':checked');
220
+ toggleSection('#section-service-scan', showService);
171
221
  }
172
222
 
173
223
  function toggleSection(selector, show) {
@@ -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>
@@ -3,45 +3,43 @@
3
3
  {% block content %}
4
4
  <div id="header">
5
5
  <!-- Header and Scan Submission Inline -->
6
- <div class="d-flex justify-content-between align-items-center flex-nowrap">
6
+ <div class="d-flex justify-content-between align-items-center flex-wrap">
7
7
  <a href="/" class="text-decoration-none" aria-label="Go to homepage">
8
8
  <h1 class="title">
9
9
  <span>LAN</span>scape
10
10
  </h1>
11
11
  </a>
12
12
  <!-- Right side: settings + form -->
13
- <div class="d-flex align-items-center justify-content-end ms-auto">
14
- <form id="scan-form" class="d-flex align-items-center">
15
- <div class="form-group me-2">
16
- <!-- Above subnet input -->
17
- <div class="label-container">
18
- <label for="subnet">Subnet:</label>
19
- <div id="subnet-info"></div>
20
- </div>
21
- <!-- Subnet input with dropdown -->
22
- <div class="input-group">
23
- <button
24
- type="button"
25
- id="settings-btn"
26
- class="btn btn-secondary start material-symbols-outlined"
27
- data-bs-toggle="tooltip"
28
- data-bs-placement="bottom"
29
- title="Advanced scan settings"
30
- >
31
- settings
32
- </button>
33
- <input type="text" id="subnet" name="subnet" class="form-control" value="{{ subnet }}" placeholder="Enter subnet">
34
- <button class="btn btn-secondary dropdown-toggle end" type="button" id="subnet-dropdown" data-bs-toggle="dropdown" aria-expanded="false"></button>
35
- <ul class="dropdown-menu" aria-labelledby="subnet-dropdown" id="dropdown-list">
36
- {% for subnet_option in alternate_subnets %}
37
- <li><a class="dropdown-item" href="#">{{ subnet_option['subnet'] }}</a></li>
38
- {% endfor %}
39
- </ul>
40
- </div>
13
+ <form id="scan-form" class="d-flex align-items-end">
14
+ <div class="form-group me-2">
15
+ <!-- Above subnet input -->
16
+ <div class="label-container">
17
+ <label for="subnet">Subnet:</label>
18
+ <div id="subnet-info"></div>
41
19
  </div>
42
- <button type="submit" id="scan-submit" class="btn btn-primary">Scan</button>
43
- </form>
44
- </div>
20
+ <!-- Subnet input with dropdown -->
21
+ <div class="input-group">
22
+ <button
23
+ type="button"
24
+ id="settings-btn"
25
+ class="btn btn-secondary start"
26
+ data-bs-toggle="tooltip"
27
+ data-bs-placement="bottom"
28
+ title="Advanced scan settings"
29
+ >
30
+ <i class="fa-solid fa-gear"></i>
31
+ </button>
32
+ <input type="text" id="subnet" name="subnet" class="form-control" value="{{ subnet }}" placeholder="Enter subnet">
33
+ <button class="btn btn-secondary dropdown-toggle end" type="button" id="subnet-dropdown" data-bs-toggle="dropdown" aria-expanded="false"></button>
34
+ <ul class="dropdown-menu" aria-labelledby="subnet-dropdown" id="dropdown-list">
35
+ {% for subnet_option in alternate_subnets %}
36
+ <li><a class="dropdown-item" href="#">{{ subnet_option['subnet'] }}</a></li>
37
+ {% endfor %}
38
+ </ul>
39
+ </div>
40
+ </div>
41
+ <button type="submit" id="scan-submit" class="btn btn-primary">Scan</button>
42
+ </form>
45
43
  </div>
46
44
 
47
45
  <div id="scan-progress-bar"></div>
@@ -59,13 +57,12 @@
59
57
  <h2>Scan Results</h2>
60
58
  <div id="scan-actions">
61
59
  <a href="" id="export-link">
62
- <span
63
- class="material-symbols-outlined secondary-icon-btn"
60
+ <i
61
+ class="fa-solid fa-upload secondary-icon-btn"
64
62
  data-bs-toggle="tooltip"
65
63
  data-bs-placement="top"
66
64
  title="Export scan to json">
67
- ios_share
68
- </span>
65
+ </i>
69
66
  </a>
70
67
  </div>
71
68
  </div>