updated formatting for the output of wordlists and standardizing

This commit is contained in:
Justin Bollinger
2026-02-02 12:30:06 -05:00
parent fe8bde2302
commit 4fa8af4684
4 changed files with 82 additions and 21 deletions
+20 -18
View File
@@ -10,6 +10,7 @@ from typing import Callable, Tuple
import requests
from bs4 import BeautifulSoup
from hate_crack.formatting import print_multicolumn_list
_TORRENT_CLEANUP_REGISTERED = False
def check_7z():
@@ -351,21 +352,15 @@ def weakpass_wordlist_menu(rank=-1):
else:
# Default: show all with rank > 4
filtered_wordlists = [wl for wl in all_wordlists if str(wl.get('rank', '')) > '4']
col_width = 45
cols = 3
print("\nEach entry shows: [number]. [wordlist name] [effectiveness score] [rank]")
print(f"Available Wordlists:")
rows = (len(filtered_wordlists) + cols - 1) // cols
lines = [''] * rows
entries = []
for idx, wl in enumerate(filtered_wordlists):
col = idx // rows
row = idx % rows
effectiveness = wl.get('effectiveness', wl.get('downloads', ''))
rank = wl.get('rank', '')
entry = f"{idx+1:3d}. {wl['name'][:25]:<25} {effectiveness:<8} {rank:<2}"
lines[row] += entry.ljust(col_width)
for line in lines:
print(line)
name = str(wl.get('name', ''))[:30]
entry = f"{idx+1:3d}. {name:<30} {effectiveness:<8} {rank:<2}"
entries.append(entry)
print_multicolumn_list("Available Wordlists", entries, min_col_width=36, max_col_width=70)
def parse_indices(selection, max_index):
indices = set()
for part in selection.split(','):
@@ -877,9 +872,16 @@ def download_hashmob_wordlist_list():
resp.raise_for_status()
data = resp.json()
wordlists = [r for r in data if r.get('type') == 'wordlist']
print("Available Hashmob Wordlists:")
entries = []
for idx, wl in enumerate(wordlists):
print(f"{idx+1}. {wl.get('name', wl.get('file_name', ''))} - {wl.get('information', '')}")
name = wl.get('name', wl.get('file_name', ''))
info = wl.get('information', '')
if info:
entry = f"{idx+1}. {name} - {info}"
else:
entry = f"{idx+1}. {name}"
entries.append(entry)
print_multicolumn_list("Available Hashmob Wordlists", entries, min_col_width=30, max_col_width=80)
return wordlists
except Exception as e:
print(f"Error fetching Hashmob wordlists: {e}")
@@ -1033,9 +1035,8 @@ def list_official_wordlists():
resp.raise_for_status()
try:
data = resp.json()
print("Official Hashmob Wordlists (JSON):")
for idx, entry in enumerate(data):
print(f"{idx+1}. {entry}")
entries = [f"{idx+1}. {entry}" for idx, entry in enumerate(data)]
print_multicolumn_list("Official Hashmob Wordlists (JSON)", entries, min_col_width=30, max_col_width=80)
return data
except Exception:
print("Official Hashmob Wordlists (raw text):")
@@ -1057,11 +1058,12 @@ def list_and_download_official_wordlists():
print("Unexpected response format. Raw output:")
print(data)
return
print("Official Hashmob Wordlists:")
entries = []
for idx, entry in enumerate(data):
name = entry.get('name', entry.get('file_name', str(entry)))
file_name = entry.get('file_name', name)
print(f"{idx+1}. {name} ({file_name})")
entries.append(f"{idx+1}. {name} ({file_name})")
print_multicolumn_list("Official Hashmob Wordlists", entries, min_col_width=30, max_col_width=80)
print("a. Download ALL files")
def _safe_input(prompt):
try:
+3 -3
View File
@@ -3,6 +3,7 @@ import os
import readline
from typing import Any
from hate_crack.formatting import print_multicolumn_list
def _configure_readline(completer):
readline.set_completer_delims(' \t\n;')
@@ -27,9 +28,8 @@ def quick_crack(ctx: Any) -> None:
selected_hcatRules = []
wordlist_files = sorted(os.listdir(ctx.hcatWordlists))
print("\nWordlists:")
for i, file in enumerate(wordlist_files, start=1):
print(f"{i}. {file}")
wordlist_entries = [f"{i}. {file}" for i, file in enumerate(wordlist_files, start=1)]
print_multicolumn_list("Wordlists", wordlist_entries, min_col_width=24, max_col_width=60)
def path_completer(text, state):
if not text:
+46
View File
@@ -0,0 +1,46 @@
import os
def _terminal_width(default: int = 120) -> int:
try:
return os.get_terminal_size().columns
except Exception:
return default
def print_multicolumn_list(title, entries, min_col_width=20, max_col_width=None):
if not entries:
if title:
print(f"\n{title}:\n (none)")
return
terminal_width = _terminal_width()
max_len = max(len(entry) for entry in entries)
if max_col_width is None:
max_col_width = max_len + 2
col_width = max(min_col_width, min(max_col_width, terminal_width))
num_cols = max(1, terminal_width // col_width)
rows = (len(entries) + num_cols - 1) // num_cols
if title:
print("\n" + "=" * terminal_width)
print(title)
print("=" * terminal_width)
for row in range(rows):
line_parts = []
for col in range(num_cols):
idx = row + col * rows
if idx < len(entries):
entry = entries[idx]
max_entry_len = max(1, col_width - 2)
if len(entry) > max_entry_len:
if max_entry_len > 3:
entry = entry[: max_entry_len - 3] + "..."
else:
entry = entry[:max_entry_len]
line_parts.append(entry.ljust(col_width))
print("".join(line_parts).rstrip())
if title:
print("=" * terminal_width)
+13
View File
@@ -340,6 +340,13 @@ hcatExpanderBin = "expander.bin"
hcatCombinatorBin = "combinator.bin"
hcatPrinceBin = "pp64.bin"
def _make_abs_wordlist(base_dir, wordlist):
if not wordlist:
return wordlist
if os.path.isabs(wordlist):
return wordlist
return os.path.abspath(os.path.join(base_dir, wordlist))
def get_rule_path(rule_name, fallback_dir=None):
candidates = []
if rulesDirectory:
@@ -464,6 +471,12 @@ if not SKIP_INIT:
# Allow module to load even if initialization fails
pass
# Normalize prince wordlist to an absolute path
wordlists_dir = hcatWordlists or os.path.join(hate_path, "wordlists")
if not os.path.isabs(wordlists_dir):
wordlists_dir = os.path.join(hate_path, wordlists_dir)
hcatPrinceBaseList = _make_abs_wordlist(wordlists_dir, hcatPrinceBaseList)
hcatHashCount = 0
hcatHashCracked = 0