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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portune
3
- Version: 0.1.4
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
+ [![Pypi version](https://img.shields.io/pypi/v/portune.svg)](https://pypi.org/project/portune/)
56
+ ![example](https://github.com/joknarf/portune/actions/workflows/python-publish.yml/badge.svg)
57
+ [![Licence](https://img.shields.io/badge/licence-MIT-blue.svg)](https://shields.io/)
58
+ [![](https://pepy.tech/badge/portune)](https://pepy.tech/project/portune)
59
+ [![Python versions](https://img.shields.io/badge/python-3.9+-blue.svg)](https://shields.io/)
60
+
55
61
  # portune
56
62
 
57
63
  Multitreaded port scanner
@@ -0,0 +1,17 @@
1
+ [![Pypi version](https://img.shields.io/pypi/v/portune.svg)](https://pypi.org/project/portune/)
2
+ ![example](https://github.com/joknarf/portune/actions/workflows/python-publish.yml/badge.svg)
3
+ [![Licence](https://img.shields.io/badge/licence-MIT-blue.svg)](https://shields.io/)
4
+ [![](https://pepy.tech/badge/portune)](https://pepy.tech/project/portune)
5
+ [![Python versions](https://img.shields.io/badge/python-3.9+-blue.svg)](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: 300px;
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: 14px;
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
- padding: 0px 4px;
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 = '&#11014;'; // Unicode for sort icon
248
+ sortBtn.innerHTML = '▲' //'&#11014;'; // 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
- contentSpan.appendChild(header.firstChild);
249
- }
258
+ //while (header.firstChild) {
259
+ // contentSpan.appendChild(header.firstChild);
260
+ //}
250
261
 
251
262
  // Add sort button at the beginning
252
- contentSpan.insertBefore(sortBtn, contentSpan.firstChild);
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 = 'column-filter';
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 = `<span>&#9660;</span> ${count}`; // &#129095;🡇 not working macOS
297
+ rowCount.innerHTML = ` ${count}`; // &#129095;🡇 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 = '&#11014;';
306
+ btn.innerHTML = '▲'; //'&#11014;';
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 = '&#11015;';
315
+ sortBtn.innerHTML = '▼'; //'&#11015;';
301
316
  } else if (currentOrder === 'desc') {
302
317
  newOrder = '';
303
- sortBtn.innerHTML = '&#11014;';
318
+ sortBtn.innerHTML = '▲'; //'&#11014;';
304
319
  } else {
305
- sortBtn.innerHTML = '&#11014;';
320
+ sortBtn.innerHTML = '▲'; //'&#11014;';
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-content')?.textContent.replace(/[▼].*/, '').replace(/[^\\w\\s]/g, '').trim() || '');
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
- command = ['ping', '-c', '1', '-W', str(int(timeout)), ip]
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
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.1.4'
21
- __version_tuple__ = version_tuple = (0, 1, 4)
20
+ __version__ = version = '0.1.6'
21
+ __version_tuple__ = version_tuple = (0, 1, 6)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portune
3
- Version: 0.1.4
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
+ [![Pypi version](https://img.shields.io/pypi/v/portune.svg)](https://pypi.org/project/portune/)
56
+ ![example](https://github.com/joknarf/portune/actions/workflows/python-publish.yml/badge.svg)
57
+ [![Licence](https://img.shields.io/badge/licence-MIT-blue.svg)](https://shields.io/)
58
+ [![](https://pepy.tech/badge/portune)](https://pepy.tech/project/portune)
59
+ [![Python versions](https://img.shields.io/badge/python-3.9+-blue.svg)](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