portune 0.1.4__tar.gz → 0.1.6__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 portune might be problematic. Click here for more details.
- {portune-0.1.4/portune.egg-info → portune-0.1.6}/PKG-INFO +7 -1
- portune-0.1.6/README.md +17 -0
- {portune-0.1.4 → portune-0.1.6}/portune/portune.py +49 -21
- {portune-0.1.4 → portune-0.1.6}/portune/version.py +2 -2
- {portune-0.1.4 → portune-0.1.6/portune.egg-info}/PKG-INFO +7 -1
- portune-0.1.4/README.md +0 -11
- {portune-0.1.4 → portune-0.1.6}/.github/workflows/python-publish.yml +0 -0
- {portune-0.1.4 → portune-0.1.6}/.gitignore +0 -0
- {portune-0.1.4 → portune-0.1.6}/LICENSE +0 -0
- {portune-0.1.4 → portune-0.1.6}/portune/__init__.py +0 -0
- {portune-0.1.4 → portune-0.1.6}/portune.egg-info/SOURCES.txt +0 -0
- {portune-0.1.4 → portune-0.1.6}/portune.egg-info/dependency_links.txt +0 -0
- {portune-0.1.4 → portune-0.1.6}/portune.egg-info/entry_points.txt +0 -0
- {portune-0.1.4 → portune-0.1.6}/portune.egg-info/top_level.txt +0 -0
- {portune-0.1.4 → portune-0.1.6}/pyproject.toml +0 -0
- {portune-0.1.4 → portune-0.1.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: portune
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Simple Python HTTP Exec Server
|
|
5
5
|
Author: Franck Jouvanceau
|
|
6
6
|
Maintainer: Franck Jouvanceau
|
|
@@ -52,6 +52,12 @@ Description-Content-Type: text/markdown
|
|
|
52
52
|
License-File: LICENSE
|
|
53
53
|
Dynamic: license-file
|
|
54
54
|
|
|
55
|
+
[](https://pypi.org/project/portune/)
|
|
56
|
+

|
|
57
|
+
[](https://shields.io/)
|
|
58
|
+
[](https://pepy.tech/project/portune)
|
|
59
|
+
[](https://shields.io/)
|
|
60
|
+
|
|
55
61
|
# portune
|
|
56
62
|
|
|
57
63
|
Multitreaded port scanner
|
portune-0.1.6/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[](https://pypi.org/project/portune/)
|
|
2
|
+

|
|
3
|
+
[](https://shields.io/)
|
|
4
|
+
[](https://pepy.tech/project/portune)
|
|
5
|
+
[](https://shields.io/)
|
|
6
|
+
|
|
7
|
+
# portune
|
|
8
|
+
|
|
9
|
+
Multitreaded port scanner
|
|
10
|
+
|
|
11
|
+
# features
|
|
12
|
+
|
|
13
|
+
* parallel check of port availability against servers/ports
|
|
14
|
+
* console output result / summary
|
|
15
|
+
* html full report / dns domain summary / vlan timeout summary
|
|
16
|
+
* mail with html summary / report attachment (mailhost relay)
|
|
17
|
+
|
|
@@ -16,6 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
# Standard library imports
|
|
17
17
|
import os
|
|
18
18
|
import sys
|
|
19
|
+
import platform
|
|
19
20
|
import argparse
|
|
20
21
|
import socket
|
|
21
22
|
import threading
|
|
@@ -32,6 +33,7 @@ from typing import List, Dict, Tuple, Any, Optional, Union
|
|
|
32
33
|
|
|
33
34
|
# Constants and global variables
|
|
34
35
|
ICON = "data:image/svg+xml,%3Csvg height='200px' width='200px' version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 508 508' xml:space='preserve' fill='%23000000'%3E%3Cg id='SVGRepo_bgCarrier' stroke-width='0'%3E%3C/g%3E%3Cg id='SVGRepo_tracerCarrier' stroke-linecap='round' stroke-linejoin='round'%3E%3C/g%3E%3Cg id='SVGRepo_iconCarrier'%3E%3Ccircle style='fill:%23ffbb06;' cx='254' cy='254' r='254'%3E%3C/circle%3E%3Cg%3E%3Ccircle style='fill:%234c4c4c;' cx='399.6' cy='252' r='55.2'%3E%3C/circle%3E%3Ccircle style='fill:%234c4c4c;' cx='150' cy='356' r='55.2'%3E%3C/circle%3E%3Ccircle style='fill:%234c4c4c;' cx='178.4' cy='127.2' r='55.2'%3E%3C/circle%3E%3C/g%3E%3Cpath style='fill:%23000000;' d='M301.2,282.4l15.6,1.2l6.4-19.2l-13.2-8c0.4-5.6,0-11.2-1.2-16.4l12-10l-9.2-18l-15.2,3.6 c-3.6-4-7.6-8-12.4-10.8l1.2-15.6l-19.2-6.4l-8,13.2c-5.6-0.4-11.2,0-16.4,1.2l-10-12l-18,8.8l3.6,15.2c-4,3.6-8,7.6-10.8,12.4 l-15.6-1.2l-6.4,19.2l13.2,8.4c-0.4,5.6,0,11.2,1.2,16.4l-12,10l9.2,18l15.2-3.6c3.6,4,7.6,8,12.4,10.8l-1.6,15.2l19.2,6.4l8.4-13.2 c5.6,0.4,11.2,0,16.4-1.2l10,12l18-8.8l-3.6-15.2C294.4,291.2,298.4,287.2,301.2,282.4z M242.4,286c-18.8-6.4-28.8-26.4-22.8-45.2 c6.4-18.8,26.8-29.2,45.6-22.8c18.8,6.4,28.8,26.4,22.8,45.2C281.6,282,261.2,292.4,242.4,286z'%3E%3C/path%3E%3Cpath style='fill:%23324A5E;' d='M380.4,304c-20.4,50-69.6,85.2-126.8,85.2c-18.8,0-36.8-4-53.6-10.8c-2.4,5.6-5.6,10.4-9.6,14.8 c19.2,8.8,40.8,13.6,63.2,13.6c65.6,0,122-41.2,144.4-99.2C392,307.2,386,306,380.4,304z M132,157.2c-20.4,26-32.8,59.2-32.8,94.8 c0,22.4,4.8,43.6,13.6,62.8c4.4-4,9.2-7.2,14.8-9.6c-6.8-16.4-10.8-34.4-10.8-53.2c0-30.4,10-58.8,27.2-81.6 C139.2,166.8,135.2,162.4,132,157.2z M253.6,97.6c-9.2,0-18.4,0.8-27.6,2.4c2.8,5.2,5.2,10.8,6.4,16.8c6.8-1.2,14-1.6,21.2-1.6 c57.2,0,106.4,35.2,126.8,85.2c5.6-2,11.2-3.2,17.2-3.2C375.6,138.8,319.6,97.6,253.6,97.6z'%3E%3C/path%3E%3Cg%3E%3Ccircle style='fill:%23FF7058;' cx='399.6' cy='252' r='28.4'%3E%3C/circle%3E%3Ccircle style='fill:%23FF7058;' cx='150' cy='356' r='28.4'%3E%3C/circle%3E%3Ccircle style='fill:%23FF7058;' cx='178.4' cy='127.2' r='28.4'%3E%3C/circle%3E%3C/g%3E%3C/g%3E%3C/svg%3E"
|
|
36
|
+
XL='data:image/svg+xml,<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M12.5535 16.5061C12.4114 16.6615 12.2106 16.75 12 16.75C11.7894 16.75 11.5886 16.6615 11.4465 16.5061L7.44648 12.1311C7.16698 11.8254 7.18822 11.351 7.49392 11.0715C7.79963 10.792 8.27402 10.8132 8.55352 11.1189L11.25 14.0682V3C11.25 2.58579 11.5858 2.25 12 2.25C12.4142 2.25 12.75 2.58579 12.75 3V14.0682L15.4465 11.1189C15.726 10.8132 16.2004 10.792 16.5061 11.0715C16.8118 11.351 16.833 11.8254 16.5535 12.1311L12.5535 16.5061Z" fill="%23eee"></path><path d="M3.75 15C3.75 14.5858 3.41422 14.25 3 14.25C2.58579 14.25 2.25 14.5858 2.25 15V15.0549C2.24998 16.4225 2.24996 17.5248 2.36652 18.3918C2.48754 19.2919 2.74643 20.0497 3.34835 20.6516C3.95027 21.2536 4.70814 21.5125 5.60825 21.6335C6.47522 21.75 7.57754 21.75 8.94513 21.75H15.0549C16.4225 21.75 17.5248 21.75 18.3918 21.6335C19.2919 21.5125 20.0497 21.2536 20.6517 20.6516C21.2536 20.0497 21.5125 19.2919 21.6335 18.3918C21.75 17.5248 21.75 16.4225 21.75 15.0549V15C21.75 14.5858 21.4142 14.25 21 14.25C20.5858 14.25 20.25 14.5858 20.25 15C20.25 16.4354 20.2484 17.4365 20.1469 18.1919C20.0482 18.9257 19.8678 19.3142 19.591 19.591C19.3142 19.8678 18.9257 20.0482 18.1919 20.1469C17.4365 20.2484 16.4354 20.25 15 20.25H9C7.56459 20.25 6.56347 20.2484 5.80812 20.1469C5.07435 20.0482 4.68577 19.8678 4.40901 19.591C4.13225 19.3142 3.9518 18.9257 3.85315 18.1919C3.75159 17.4365 3.75 16.4354 3.75 15Z" fill="%23eee"></path></g></svg>'
|
|
35
37
|
CSS="""
|
|
36
38
|
<style>
|
|
37
39
|
body {
|
|
@@ -82,7 +84,7 @@ div {
|
|
|
82
84
|
}
|
|
83
85
|
.desc {
|
|
84
86
|
text-overflow: ellipsis;
|
|
85
|
-
max-width:
|
|
87
|
+
max-width: 200px;
|
|
86
88
|
white-space: nowrap;
|
|
87
89
|
overflow: hidden;
|
|
88
90
|
}
|
|
@@ -136,7 +138,7 @@ th {
|
|
|
136
138
|
}
|
|
137
139
|
.sort-btn {
|
|
138
140
|
color: #aaa;
|
|
139
|
-
font-size:
|
|
141
|
+
font-size: 10px;
|
|
140
142
|
user-select: none;
|
|
141
143
|
display: inline-block;
|
|
142
144
|
width: 7px;
|
|
@@ -218,13 +220,18 @@ th {
|
|
|
218
220
|
border-radius: 17px;
|
|
219
221
|
/* min-width: 17px; */
|
|
220
222
|
text-align: center;
|
|
221
|
-
|
|
223
|
+
/* text-indent: 14px;*/
|
|
224
|
+
padding: 0px 18px 0px 4px;
|
|
222
225
|
margin-left: auto;
|
|
223
226
|
cursor: pointer;
|
|
227
|
+
background-image: url('{XL}');
|
|
228
|
+
background-repeat: no-repeat;
|
|
229
|
+
background-position: right 4px center;
|
|
230
|
+
background-size: 12px 12px;
|
|
224
231
|
}
|
|
225
232
|
|
|
226
233
|
</style>
|
|
227
|
-
""".replace("{ICON}", ICON)
|
|
234
|
+
""".replace("{ICON}", ICON).replace("{XL}", XL)
|
|
228
235
|
JS="""
|
|
229
236
|
<script src=https://unpkg.com/exceljs@4.1.1/dist/exceljs.min.js></script>
|
|
230
237
|
<script>
|
|
@@ -238,18 +245,25 @@ function initTableFilters(table) {
|
|
|
238
245
|
// Add sort button first
|
|
239
246
|
const sortBtn = document.createElement('span');
|
|
240
247
|
sortBtn.className = 'sort-btn';
|
|
241
|
-
sortBtn.innerHTML = '⬆'; // Unicode for sort icon
|
|
248
|
+
sortBtn.innerHTML = '▲' //'⬆'; // Unicode for sort icon ▼
|
|
242
249
|
sortBtn.style.cursor = 'pointer';
|
|
243
250
|
sortBtn.setAttribute('data-sort-order', '');
|
|
244
251
|
sortBtn.onclick = () => toggleSort(table, index, sortBtn);
|
|
245
|
-
|
|
252
|
+
|
|
253
|
+
const titleSpan = document.createElement('span');
|
|
254
|
+
titleSpan.className = 'th-title';
|
|
255
|
+
titleSpan.innerHTML = header.innerHTML;
|
|
256
|
+
|
|
246
257
|
// Move existing elements into the content span
|
|
247
|
-
while (header.firstChild) {
|
|
248
|
-
|
|
249
|
-
}
|
|
258
|
+
//while (header.firstChild) {
|
|
259
|
+
// contentSpan.appendChild(header.firstChild);
|
|
260
|
+
//}
|
|
250
261
|
|
|
251
262
|
// Add sort button at the beginning
|
|
252
|
-
contentSpan.
|
|
263
|
+
contentSpan.appendChild(sortBtn);
|
|
264
|
+
contentSpan.appendChild(titleSpan);
|
|
265
|
+
|
|
266
|
+
//contentSpan.insertBefore(sortBtn, contentSpan.firstChild);
|
|
253
267
|
|
|
254
268
|
// Add export button and row counter for last column
|
|
255
269
|
if (index === headers.length - 1) {
|
|
@@ -261,13 +275,14 @@ function initTableFilters(table) {
|
|
|
261
275
|
contentSpan.appendChild(rowCount);
|
|
262
276
|
}
|
|
263
277
|
|
|
278
|
+
header.innerHTML = '';
|
|
264
279
|
header.appendChild(contentSpan);
|
|
265
280
|
|
|
266
281
|
// Add filter input
|
|
267
282
|
const input = document.createElement('input');
|
|
268
283
|
input.type = 'search';
|
|
269
|
-
input.className =
|
|
270
|
-
input.placeholder = '\\uD83D\\uDD0E\\uFE0E';
|
|
284
|
+
input.className = `column-filter input-${index}`;
|
|
285
|
+
input.placeholder = '\\uD83D\\uDD0E\\uFE0E';
|
|
271
286
|
input.addEventListener('input', () => applyFilters(table));
|
|
272
287
|
header.appendChild(input);
|
|
273
288
|
}
|
|
@@ -279,7 +294,7 @@ function initTableFilters(table) {
|
|
|
279
294
|
function updateRowCount(table, count) {
|
|
280
295
|
const rowCount = table.querySelector('.row-count');
|
|
281
296
|
if (rowCount) {
|
|
282
|
-
rowCount.innerHTML =
|
|
297
|
+
rowCount.innerHTML = ` ${count}`; // 🡇🡇 not working macOS
|
|
283
298
|
}
|
|
284
299
|
}
|
|
285
300
|
|
|
@@ -288,7 +303,7 @@ function toggleSort(table, colIndex, sortBtn) {
|
|
|
288
303
|
table.querySelectorAll('.sort-btn').forEach(btn => {
|
|
289
304
|
if (btn !== sortBtn) {
|
|
290
305
|
btn.setAttribute('data-sort-order', '');
|
|
291
|
-
btn.innerHTML = '⬆';
|
|
306
|
+
btn.innerHTML = '▲'; //'⬆';
|
|
292
307
|
}
|
|
293
308
|
});
|
|
294
309
|
|
|
@@ -297,12 +312,12 @@ function toggleSort(table, colIndex, sortBtn) {
|
|
|
297
312
|
let newOrder = 'asc';
|
|
298
313
|
if (currentOrder === 'asc') {
|
|
299
314
|
newOrder = 'desc';
|
|
300
|
-
sortBtn.innerHTML = '⬇';
|
|
315
|
+
sortBtn.innerHTML = '▼'; //'⬇';
|
|
301
316
|
} else if (currentOrder === 'desc') {
|
|
302
317
|
newOrder = '';
|
|
303
|
-
sortBtn.innerHTML = '⬆';
|
|
318
|
+
sortBtn.innerHTML = '▲'; //'⬆';
|
|
304
319
|
} else {
|
|
305
|
-
sortBtn.innerHTML = '⬆';
|
|
320
|
+
sortBtn.innerHTML = '▲'; //'⬆';
|
|
306
321
|
}
|
|
307
322
|
sortBtn.setAttribute('data-sort-order', newOrder);
|
|
308
323
|
sortBtn.setAttribute('data-col-index', colIndex); // Store column index on the button
|
|
@@ -433,7 +448,7 @@ function exportToExcel(table, fileNamePrefix = 'export') {
|
|
|
433
448
|
|
|
434
449
|
// Get headers and data
|
|
435
450
|
const headers = Array.from(table.querySelectorAll('thead th'))
|
|
436
|
-
.map(th => th.querySelector('.th-
|
|
451
|
+
.map(th => th.querySelector('.th-title')?.textContent.trim() || '');
|
|
437
452
|
|
|
438
453
|
// Get data rows with type information
|
|
439
454
|
const rows = Array.from(table.querySelectorAll('tbody tr'))
|
|
@@ -532,6 +547,7 @@ function exportToExcel(table, fileNamePrefix = 'export') {
|
|
|
532
547
|
let commandsTable = document.querySelector('#commandTable');
|
|
533
548
|
document.addEventListener('DOMContentLoaded', () => {
|
|
534
549
|
if (commandsTable) initTableFilters(commandsTable);
|
|
550
|
+
document.querySelector('.input-4').value = '{FILTER}';
|
|
535
551
|
});
|
|
536
552
|
</script>
|
|
537
553
|
"""
|
|
@@ -670,8 +686,12 @@ def ping_host(ip: str, timeout: float = 2.0) -> bool:
|
|
|
670
686
|
"""
|
|
671
687
|
try:
|
|
672
688
|
# Using -c 1 for count=1, -W timeout for timeout in seconds
|
|
689
|
+
# Windows uses -n 1 for count=1, -w timeout in milliseconds
|
|
673
690
|
# These are standard Linux ping parameters
|
|
674
|
-
|
|
691
|
+
if platform.system().lower() == "windows":
|
|
692
|
+
command = ["ping", "-n", "1", "-w", str(int(timeout * 1000)), ip]
|
|
693
|
+
else:
|
|
694
|
+
command = ['ping', '-c', '1', '-W', str(int(timeout)), ip]
|
|
675
695
|
output = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout)
|
|
676
696
|
return output.returncode == 0
|
|
677
697
|
except Exception:
|
|
@@ -1168,6 +1188,7 @@ def generate_html_report(
|
|
|
1168
1188
|
stats: Dict[str, Any],
|
|
1169
1189
|
input_file: str = '',
|
|
1170
1190
|
desc_titles: List[str] = [],
|
|
1191
|
+
filter: str = '',
|
|
1171
1192
|
) -> None:
|
|
1172
1193
|
"""Generate a complete HTML report of the port scan results.
|
|
1173
1194
|
|
|
@@ -1237,8 +1258,11 @@ def generate_html_report(
|
|
|
1237
1258
|
ping_status = 'UP' if ping else 'N/A' if noping else 'DOWN'
|
|
1238
1259
|
ping_class = 'green' if ping else 'blue' if noping else 'red'
|
|
1239
1260
|
status_class = 'green' if status == 'CONNECTED' else 'blue' if status == 'REFUSED' else 'red'
|
|
1261
|
+
row_class = ''
|
|
1262
|
+
if filter and status != filter:
|
|
1263
|
+
row_class = 'hidden'
|
|
1240
1264
|
f.write(f'''
|
|
1241
|
-
<tr>
|
|
1265
|
+
<tr class="{row_class}">
|
|
1242
1266
|
<td>{escape(str(hostname))}</td>
|
|
1243
1267
|
<td>{escape(str(ip))}</td>
|
|
1244
1268
|
<td>{str(get_vlan_base(ip, stats['vlan_bits']))}</td>
|
|
@@ -1255,7 +1279,7 @@ def generate_html_report(
|
|
|
1255
1279
|
f.write(generate_html_summary(stats, parallelism, timeout))
|
|
1256
1280
|
|
|
1257
1281
|
# Add JavaScript for interactivity
|
|
1258
|
-
f.write(f'</body>{JS}</html>\n')
|
|
1282
|
+
f.write(f'</body>{JS.replace("{FILTER}", filter)}</html>\n')
|
|
1259
1283
|
|
|
1260
1284
|
def print_statistics(stats, timeout, parallelism):
|
|
1261
1285
|
def format_percent(value, total):
|
|
@@ -1430,6 +1454,9 @@ def main():
|
|
|
1430
1454
|
parser.add_argument('-s', '--summary', action="store_true", help='Print scan summary information')
|
|
1431
1455
|
parser.add_argument('-b', '--bits', type=int, default=16, help='VLAN bits for timeout summary (default: 16)')
|
|
1432
1456
|
parser.add_argument('-d', '--desc_titles', type=str, nargs='*', help='List of custom description titles for hosts (optional)')
|
|
1457
|
+
parser.add_argument('-f', '--filter', type=str, help='default status filter for html report (optional)',
|
|
1458
|
+
choices=['CONNECTED', 'REFUSED', 'TIMEOUT', 'UNREACHABLE', 'RESOLVE_FAIL'], default='')
|
|
1459
|
+
|
|
1433
1460
|
# Email related arguments
|
|
1434
1461
|
email_group = parser.add_argument_group('Email Options')
|
|
1435
1462
|
email_group.add_argument('--email-to', help='Comma-separated list of email recipients')
|
|
@@ -1497,6 +1524,7 @@ def main():
|
|
|
1497
1524
|
stats,
|
|
1498
1525
|
args.input_file,
|
|
1499
1526
|
args.desc_titles,
|
|
1527
|
+
args.filter,
|
|
1500
1528
|
)
|
|
1501
1529
|
|
|
1502
1530
|
# Print summary
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: portune
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Simple Python HTTP Exec Server
|
|
5
5
|
Author: Franck Jouvanceau
|
|
6
6
|
Maintainer: Franck Jouvanceau
|
|
@@ -52,6 +52,12 @@ Description-Content-Type: text/markdown
|
|
|
52
52
|
License-File: LICENSE
|
|
53
53
|
Dynamic: license-file
|
|
54
54
|
|
|
55
|
+
[](https://pypi.org/project/portune/)
|
|
56
|
+

|
|
57
|
+
[](https://shields.io/)
|
|
58
|
+
[](https://pepy.tech/project/portune)
|
|
59
|
+
[](https://shields.io/)
|
|
60
|
+
|
|
55
61
|
# portune
|
|
56
62
|
|
|
57
63
|
Multitreaded port scanner
|
portune-0.1.4/README.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# portune
|
|
2
|
-
|
|
3
|
-
Multitreaded port scanner
|
|
4
|
-
|
|
5
|
-
# features
|
|
6
|
-
|
|
7
|
-
* parallel check of port availability against servers/ports
|
|
8
|
-
* console output result / summary
|
|
9
|
-
* html full report / dns domain summary / vlan timeout summary
|
|
10
|
-
* mail with html summary / report attachment (mailhost relay)
|
|
11
|
-
|
|
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
|