Skip to content

Commit d1eb2e9

Browse files
committed
fix(cli): implement block format for clickable full URLs and fix safe_print kwargs (v1.3.1)
1 parent 35d16ee commit d1eb2e9

File tree

4 files changed

+61
-75
lines changed

4 files changed

+61
-75
lines changed

exc_analyzer/commands/actions_audit.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,10 @@ def _print_audit_results(repo, results):
128128
else:
129129
safe_print(Print.colorize(note_line, '96'))
130130
_write_output(note_line)
131-
url_display = result['url']
132-
if len(url_display) > 55:
133-
url_display = url_display[:52] + "..."
134-
url_line = f" URL: {url_display}"
135-
safe_print(Print.colorize(url_line, '90'))
136-
_write_output(url_line)
131+
link_line_prefix = " -> "
132+
safe_print(Print.colorize(link_line_prefix, '90'), end="")
133+
safe_print(Print.colorize(result['url'], '33'))
134+
_write_output(f" -> {result['url']}")
137135
if i < len(results):
138136
safe_print("")
139137
_write_output("")

exc_analyzer/commands/advanced_secrets.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,10 @@ async def _scan_with_sem(url, path, source):
7373
source_line = f" {t('commands.advanced_secrets.output.source')}: {source}"
7474
safe_print(Print.colorize(source_line, '97'))
7575
_write_output(source_line)
76-
display_url = url
77-
if "github.com" in url and len(url) > 60:
78-
for marker in ["/raw/", "/blob/", "/commit/"]:
79-
if marker in url:
80-
parts = url.split(marker)
81-
if len(parts) == 2:
82-
base = parts[0]
83-
rest = parts[1]
84-
if len(rest) > 20:
85-
display_url = f"{base}{marker}.../{rest.split('/')[-1]}"
86-
break
87-
if display_url == url:
88-
display_url = url[:50] + "..." + url[-10:]
89-
indent = " "
90-
safe_print(indent, end="")
91-
Print.hyperlink(display_url, url)
76+
link_label = " -> "
77+
safe_print(Print.colorize(link_label, '90'), end="")
78+
safe_print(Print.colorize(url, '33'))
79+
_write_output(f" -> {url}")
9280
_write_output(f" {url}")
9381
print()
9482
_write_output("")

exc_analyzer/commands/dork_scan.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import math
77
from collections import Counter
88
from urllib.parse import quote, unquote
9-
from ..print_utils import Print, _write_output
9+
from ..print_utils import Print, _write_output, safe_print, colorize
1010
from ..api import api_get, get_auth_header
1111
from ..i18n import t
1212
from .dork_presets import PRESETS, get_preset_choices
@@ -193,30 +193,28 @@ def _calculate_entropy(text):
193193
entropy -= probability * math.log2(probability)
194194
return entropy
195195
def _print_results(results, verify_enabled=False):
196-
columns = [
197-
{'header': t("commands.dork_scan.table_header.repo"), 'width': 25, 'color': '94'},
198-
{'header': t("commands.dork_scan.table_header.file"), 'width': None, 'color': '97'},
199-
{'header': t("commands.dork_scan.table_header.link"), 'width': 35, 'color': '33'}
200-
]
201-
if verify_enabled:
202-
columns.append({'header': t("commands.dork_scan.table_header.status"), 'width': 20, 'color': '92'})
203196
safe_print("")
204-
printer = TablePrinter(columns)
205-
printer.print_header()
206-
w_repo = columns[0]['_actual_width']
207-
w_file = columns[1]['_actual_width']
208-
w_link = columns[2]['_actual_width']
209-
w_stat = columns[3]['_actual_width'] if verify_enabled else 0
210-
for i, res in enumerate(results):
211-
display_repo = _truncate(res['repo'], w_repo)
212-
display_file = smart_truncate_path(res['path'], w_file)
213-
display_link = shorten_display_url(res['url'], w_link)
214-
row = [display_repo, display_file, (display_link, res['url'])]
197+
_write_output("")
198+
for i, res in enumerate(results, 1):
199+
# Header for the result item
200+
status_part = ""
215201
if verify_enabled:
216-
row.append(_truncate(res['status'], w_stat))
217-
style = "2;" if i % 2 == 1 else ""
218-
printer.print_row(row, style_prefix=style)
202+
status = res.get('status', 'Unknown')
203+
color = '92' if status == '200 OK' else '91'
204+
status_part = f" [{Print.colorize(status, color)}]"
205+
header = f"[+] {Print.colorize(res['repo'], '94')} | {Print.colorize(res['path'], '97')}{status_part}"
206+
safe_print(header)
207+
_write_output(f"[+] {res['repo']} | {res['path']} {res.get('status', '')}")
208+
# Link part with symbolic link look
209+
link_line_prefix = " -> "
210+
safe_print(Print.colorize(link_line_prefix, '90'), end="")
211+
safe_print(Print.colorize(res['url'], '33'))
212+
_write_output(f" -> {res['url']}")
213+
if i < len(results):
214+
safe_print("")
215+
_write_output("")
219216
safe_print("")
217+
_write_output("")
220218
Print.info(t("commands.dork_scan.total", count=len(results)))
221219
Print.warn(t("commands.dork_scan.disclaimer"))
222220
safe_print("")
@@ -247,6 +245,10 @@ def _list_presets():
247245
print(f" - {k:<10} : {examples}")
248246
print()
249247
def shorten_display_url(full_url, max_len):
248+
"""
249+
Returns a shortened display text for the URL.
250+
The actual hyperlink will use the full URL (passed separately as tuple).
251+
"""
250252
try:
251253
full_url = unquote(full_url)
252254
except:
@@ -258,7 +260,7 @@ def shorten_display_url(full_url, max_len):
258260
rest = parts[1]
259261
sha_parts = rest.split("/", 1)
260262
filename = sha_parts[1].split("/")[-1] if len(sha_parts) > 1 else "file"
261-
prefix = "github.com/.../"
263+
prefix = "https://github.com/.../"
262264
available = max_len - len(prefix)
263265
if len(filename) > available:
264266
filename = _truncate(filename, available)
@@ -305,6 +307,4 @@ def _smart_quote_query(query):
305307
if f"{mod}:" in query:
306308
return query
307309
return f'"{query}"'
308-
def safe_print(msg=""):
309-
print(msg)
310-
_write_output(msg)
310+

exc_analyzer/print_utils.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -116,95 +116,95 @@ def safe_print(text='', **kwargs):
116116
_write_output(text)
117117
class Print:
118118
@staticmethod
119-
def success(msg):
119+
def success(msg, **kwargs):
120120
from exc_analyzer.i18n import t
121121
prefix = t("log_levels.success")
122122
colored_msg = colorize(f"[{prefix}] {msg}", '92')
123123
try:
124-
print(colored_msg)
124+
print(colored_msg, **kwargs)
125125
except UnicodeEncodeError:
126-
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'))
126+
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
127127
_write_output(f"[{prefix}] {msg}")
128128
@staticmethod
129-
def error(msg):
129+
def error(msg, **kwargs):
130130
from exc_analyzer.i18n import t
131131
prefix = t("log_levels.error")
132132
colored_msg = colorize(f"[{prefix}] {msg}", '91')
133133
try:
134-
print(colored_msg)
134+
print(colored_msg, **kwargs)
135135
except UnicodeEncodeError:
136-
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'))
136+
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
137137
_write_output(f"[{prefix}] {msg}")
138138
@staticmethod
139-
def warn(msg):
139+
def warn(msg, **kwargs):
140140
from exc_analyzer.i18n import t
141141
prefix = t("log_levels.warn")
142142
colored_msg = colorize(f"[{prefix}] {msg}", '93')
143143
try:
144-
print(colored_msg)
144+
print(colored_msg, **kwargs)
145145
except UnicodeEncodeError:
146-
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'))
146+
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
147147
_write_output(f"[{prefix}] {msg}")
148148
@staticmethod
149-
def info(msg):
149+
def info(msg, **kwargs):
150150
from exc_analyzer.i18n import t
151151
prefix = t("log_levels.info")
152152
colored_msg = colorize(f"[{prefix}] {msg}", '96')
153153
try:
154-
print(colored_msg)
154+
print(colored_msg, **kwargs)
155155
except UnicodeEncodeError:
156-
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'))
156+
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
157157
_write_output(f"[{prefix}] {msg}")
158158
@staticmethod
159-
def action(msg):
159+
def action(msg, **kwargs):
160160
from exc_analyzer.i18n import t
161161
prefix = t("log_levels.action")
162162
colored_msg = colorize(f"[{prefix}] {msg}", '90')
163163
try:
164-
print(colored_msg)
164+
print(colored_msg, **kwargs)
165165
except UnicodeEncodeError:
166-
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'))
166+
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
167167
_write_output(f"[{prefix}] {msg}")
168168
@staticmethod
169-
def critical_error(msg):
169+
def critical_error(msg, **kwargs):
170170
from exc_analyzer.i18n import t
171171
prefix = t("log_levels.critical_error")
172172
colored_msg = colorize(f"[{prefix}] {msg}", '1;91')
173173
try:
174-
print(colored_msg)
174+
print(colored_msg, **kwargs)
175175
except UnicodeEncodeError:
176-
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'))
176+
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
177177
_write_output(f"[{prefix}] {msg}")
178178
@staticmethod
179-
def cancelled(msg):
179+
def cancelled(msg, **kwargs):
180180
from exc_analyzer.i18n import t
181181
prefix = t("log_levels.cancelled")
182182
colored_msg = colorize(f"[{prefix}] {msg}", '90')
183183
try:
184-
print(colored_msg)
184+
print(colored_msg, **kwargs)
185185
except UnicodeEncodeError:
186-
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'))
186+
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
187187
_write_output(f"[{prefix}] {msg}")
188188
@staticmethod
189-
def link(url):
189+
def link(url, **kwargs):
190190
colored_msg = colorize(url, '94')
191191
try:
192-
print(colored_msg)
192+
print(colored_msg, **kwargs)
193193
except UnicodeEncodeError:
194-
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'))
194+
print(colored_msg.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
195195
_write_output(url)
196196
@staticmethod
197-
def hyperlink(text, url):
197+
def hyperlink(text, url, **kwargs):
198198
"""Print clickable hyperlink (OSC 8) with shortened text."""
199199
colored_text = colorize(text, '33')
200200
if COLOR_ENABLED:
201201
link_seq = f"\033]8;;{url}\033\\{colored_text}\033]8;;\033\\"
202202
else:
203203
link_seq = f"{text} ({url})"
204204
try:
205-
print(link_seq)
205+
print(link_seq, **kwargs)
206206
except UnicodeEncodeError:
207-
print(link_seq.encode('utf-8', errors='replace').decode('utf-8'))
207+
print(link_seq.encode('utf-8', errors='replace').decode('utf-8'), **kwargs)
208208
_write_output(f"{text} ({url})")
209209
@staticmethod
210210
def colorize(text, color_code):

0 commit comments

Comments
 (0)