Skip to content

Commit a824972

Browse files
committed
Fix WPS and CLI column alignment in scan display
The to_str() method used inconsistent column widths and separators that didn't match the header defined in scanner.py, causing WPS values to appear under the CLI header and client counts to overflow past the table. - Add _pad_colored() helper to pad ANSI-colored strings to exact visible widths - Use consistent 2-space separators between all columns - Match column widths (ESSID:26, BSSID:19, MFG:23, CH:4, ENCR:9, PWR:7, WPS:5, CLI:7) - Fix classic.py header to use same column order and widths as scanner.py https://claude.ai/code/session_019ijpUyTX2ZGrr1123Hteea
1 parent af8d1dd commit a824972

2 files changed

Lines changed: 70 additions & 17 deletions

File tree

wifite/model/target.py

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ class Target:
4848
"""
4949
_ansi_re = re.compile(r'\033\[[0-9;]*m')
5050

51+
def _pad_colored(self, colored_str, width, align='left'):
52+
"""Pad a colored string to a specific visible width."""
53+
visible = self._ansi_re.sub('', colored_str)
54+
diff = width - len(visible)
55+
if diff <= 0:
56+
return colored_str
57+
if align == 'right':
58+
return ' ' * diff + colored_str
59+
elif align == 'center':
60+
left_pad = diff // 2
61+
right_pad = diff - left_pad
62+
return ' ' * left_pad + colored_str + ' ' * right_pad
63+
else:
64+
return colored_str + ' ' * diff
65+
5166
def __init__(self, fields):
5267
"""
5368
Initializes & stores target info based on fields.
@@ -249,7 +264,7 @@ def to_str(self, show_bssid=False, show_manufacturer=False):
249264
decloaked_char = Color.s('{P}*') if self.decloaked else ' '
250265
essid += decloaked_char
251266

252-
bssid = Color.s('{D}%s{W} ' % self.bssid) if show_bssid else ''
267+
bssid = Color.s('{D}%s{W}' % self.bssid) if show_bssid else ''
253268
if show_manufacturer:
254269
oui = ''.join(self.bssid.split(':')[:3])
255270
self.manufacturer = Configuration.manufacturers.get(oui, "")
@@ -260,7 +275,7 @@ def to_str(self, show_bssid=False, show_manufacturer=False):
260275
mfg_name = f'{mfg_name[:max_oui_len - 3]}...'
261276
else:
262277
mfg_name = mfg_name.ljust(max_oui_len)
263-
manufacturer = Color.s('{W}%s ' % mfg_name)
278+
manufacturer = Color.s('{W}%s' % mfg_name)
264279
else:
265280
manufacturer = ''
266281

@@ -328,21 +343,44 @@ def to_str(self, show_bssid=False, show_manufacturer=False):
328343
power = f'{pwr_bar} {Color.s("{%s}%s" % (pwr_color, str(pwr_dbm).rjust(2)))}'
329344

330345
if self.wps == WPSState.UNLOCKED:
331-
wps = Color.s(' {G}yes')
346+
wps = Color.s('{G}yes')
332347
elif self.wps == WPSState.NONE:
333-
wps = Color.s(' {D} - ')
348+
wps = Color.s('{D}-')
334349
elif self.wps == WPSState.LOCKED:
335-
wps = Color.s(' {R}lck')
350+
wps = Color.s('{R}lck')
336351
elif self.wps == WPSState.UNKNOWN:
337-
wps = Color.s(' {O} ? ')
352+
wps = Color.s('{O}?')
338353
else:
339-
wps = ' - '
354+
wps = '-'
340355

341-
clients = Color.s('{D} - ')
342356
if len(self.clients) > 0:
343-
clients = Color.s('{G} %s' % str(len(self.clients)))
344-
345-
result = f'{essid} {bssid}{manufacturer}{channel} {encryption_display_string} {power} {wps} {clients}'
357+
clients = Color.s('{G}%s' % str(len(self.clients)))
358+
else:
359+
clients = Color.s('{D}-')
360+
361+
# Column widths must match scanner.py header
362+
COL_ESSID = 26
363+
COL_BSSID = 19
364+
COL_MFG = 23
365+
COL_CH = 4
366+
COL_ENC = 9
367+
COL_PWR = 7
368+
COL_WPS = 5
369+
COL_CLI = 7
370+
SEP = ' '
371+
372+
parts = [self._pad_colored(essid, COL_ESSID)]
373+
if show_bssid:
374+
parts.append(self._pad_colored(bssid, COL_BSSID))
375+
if show_manufacturer:
376+
parts.append(self._pad_colored(manufacturer, COL_MFG))
377+
parts.append(self._pad_colored(channel, COL_CH, 'right'))
378+
parts.append(self._pad_colored(encryption_display_string, COL_ENC))
379+
parts.append(self._pad_colored(power, COL_PWR, 'right'))
380+
parts.append(self._pad_colored(wps, COL_WPS, 'center'))
381+
parts.append(self._pad_colored(clients, COL_CLI, 'right'))
382+
383+
result = SEP.join(parts)
346384

347385
result += Color.s('{W}')
348386
return result

wifite/ui/classic.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,35 @@ def display_targets(self, targets, show_bssid=False, show_manufacturer=False):
4848
Color.pl('{+} {C}Targets{W}')
4949
Color.pl('')
5050

51-
# Print header
52-
header = ' NUM'
51+
# Print header (column widths must match target.to_str())
52+
col_num = 5
53+
col_essid = 26
54+
col_bssid = 19
55+
col_mfg = 23
56+
col_ch = 4
57+
col_enc = 9
58+
col_pwr = 7
59+
col_wps = 5
60+
col_cli = 7
61+
62+
header = ' ' + 'NUM'.rjust(col_num)
63+
header += ' ' + 'ESSID'.ljust(col_essid)
5364
if show_bssid:
54-
header += ' BSSID '
65+
header += ' ' + 'BSSID'.ljust(col_bssid)
5566
if show_manufacturer:
56-
header += ' MANUFACTURER '
57-
header += ' ESSID CH PWR ENC WPS CLIENT'
67+
header += ' ' + 'MANUFACTURER'.ljust(col_mfg)
68+
header += ' ' + 'CH'.rjust(col_ch)
69+
header += ' ' + 'ENCR'.ljust(col_enc)
70+
header += ' ' + 'PWR'.rjust(col_pwr)
71+
header += ' ' + 'WPS'.center(col_wps)
72+
header += ' ' + 'CLI'.rjust(col_cli)
5873
Color.pl(header)
5974
Color.pl(' ' + '-' * (len(header) - 2))
6075

6176
# Print targets
6277
for idx, target in enumerate(targets, start=1):
6378
target_str = target.to_str(show_bssid=show_bssid, show_manufacturer=show_manufacturer)
64-
Color.pl(' {G}%3d{W} %s' % (idx, target_str))
79+
Color.pl(' {G}%s{W} %s' % (str(idx).rjust(col_num), target_str))
6580

6681
Color.pl('')
6782

0 commit comments

Comments
 (0)