2025-02-11 07:15:39 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# HTTPZ Web Scanner - Developed by acidvegas in Python (https://github.com/acidvegas/httpz)
|
2025-02-11 07:46:01 +00:00
|
|
|
# httpz_scanner/formatters.py
|
2025-02-11 07:15:39 +00:00
|
|
|
|
|
|
|
from .colors import Colors
|
|
|
|
from .utils import human_size
|
|
|
|
|
|
|
|
def format_console_output(result: dict, debug: bool = False, show_fields: dict = None, match_codes: set = None, exclude_codes: set = None) -> str:
|
|
|
|
'''
|
|
|
|
Format the output with colored sections
|
|
|
|
|
|
|
|
:param result: Dictionary containing domain check results
|
|
|
|
:param debug: Whether to show error states
|
|
|
|
:param show_fields: Dictionary of fields to show
|
|
|
|
:param match_codes: Set of status codes to match
|
|
|
|
:param exclude_codes: Set of status codes to exclude
|
|
|
|
'''
|
|
|
|
if result['status'] < 0 and not debug:
|
|
|
|
return ''
|
|
|
|
|
|
|
|
if match_codes and result['status'] not in match_codes:
|
|
|
|
return ''
|
|
|
|
if exclude_codes and result['status'] in exclude_codes:
|
|
|
|
return ''
|
|
|
|
|
|
|
|
parts = []
|
|
|
|
|
|
|
|
# Status code
|
|
|
|
if show_fields.get('status_code'):
|
|
|
|
if result['status'] < 0:
|
|
|
|
status = f"{Colors.RED}[{result['status']}]{Colors.RESET}"
|
|
|
|
elif 200 <= result['status'] < 300:
|
|
|
|
status = f"{Colors.GREEN}[{result['status']}]{Colors.RESET}"
|
|
|
|
elif 300 <= result['status'] < 400:
|
|
|
|
status = f"{Colors.YELLOW}[{result['status']}]{Colors.RESET}"
|
|
|
|
else:
|
|
|
|
status = f"{Colors.RED}[{result['status']}]{Colors.RESET}"
|
|
|
|
parts.append(status)
|
|
|
|
|
|
|
|
# Domain (always shown)
|
|
|
|
parts.append(f"[{result['url']}]")
|
|
|
|
|
|
|
|
# Title
|
|
|
|
if show_fields.get('title') and result.get('title'):
|
|
|
|
parts.append(f"{Colors.DARK_GREEN}[{result['title']}]{Colors.RESET}")
|
|
|
|
|
|
|
|
# Body preview
|
|
|
|
if show_fields.get('body') and result.get('body'):
|
|
|
|
body = result['body'][:100] + ('...' if len(result['body']) > 100 else '')
|
|
|
|
parts.append(f"{Colors.BLUE}[{body}]{Colors.RESET}")
|
|
|
|
|
|
|
|
# IPs
|
|
|
|
if show_fields.get('ip') and result.get('ips'):
|
|
|
|
ips_text = ', '.join(result['ips'])
|
|
|
|
parts.append(f"{Colors.YELLOW}[{ips_text}]{Colors.RESET}")
|
|
|
|
|
|
|
|
# Favicon hash
|
|
|
|
if show_fields.get('favicon') and result.get('favicon_hash'):
|
|
|
|
parts.append(f"{Colors.PURPLE}[{result['favicon_hash']}]{Colors.RESET}")
|
|
|
|
|
|
|
|
# Headers
|
|
|
|
if show_fields.get('headers') and result.get('headers'):
|
|
|
|
headers_text = [f"{k}: {v}" for k, v in result['headers'].items()]
|
|
|
|
parts.append(f"{Colors.CYAN}[{', '.join(headers_text)}]{Colors.RESET}")
|
|
|
|
else:
|
|
|
|
if show_fields.get('content_type') and result.get('content_type'):
|
|
|
|
parts.append(f"{Colors.HEADER}[{result['content_type']}]{Colors.RESET}")
|
|
|
|
|
|
|
|
if show_fields.get('content_length') and result.get('content_length'):
|
|
|
|
try:
|
|
|
|
size = human_size(int(result['content_length']))
|
|
|
|
parts.append(f"{Colors.PINK}[{size}]{Colors.RESET}")
|
|
|
|
except (ValueError, TypeError):
|
|
|
|
parts.append(f"{Colors.PINK}[{result['content_length']}]{Colors.RESET}")
|
|
|
|
|
|
|
|
# CNAME
|
|
|
|
if show_fields.get('cname') and result.get('cname'):
|
|
|
|
parts.append(f"{Colors.PURPLE}[CNAME: {result['cname']}]{Colors.RESET}")
|
|
|
|
|
|
|
|
# Redirect Chain
|
|
|
|
if show_fields.get('follow_redirects') and result.get('redirect_chain'):
|
|
|
|
chain = ' -> '.join(result['redirect_chain'])
|
|
|
|
parts.append(f"{Colors.YELLOW}[Redirects: {chain}]{Colors.RESET}")
|
|
|
|
|
|
|
|
# TLS Certificate Info
|
|
|
|
if result.get('tls'):
|
|
|
|
cert = result['tls']
|
|
|
|
tls_parts = []
|
|
|
|
if cert.get('common_name'):
|
|
|
|
tls_parts.append(f"Subject: {cert['common_name']}")
|
|
|
|
if cert.get('issuer'):
|
|
|
|
tls_parts.append(f"Issuer: {cert['issuer']}")
|
|
|
|
if cert.get('fingerprint'):
|
|
|
|
tls_parts.append(f"Fingerprint: {cert['fingerprint'][:16]}...")
|
|
|
|
if cert.get('alt_names'):
|
|
|
|
tls_parts.append(f"SANs: {', '.join(cert['alt_names'][:3])}")
|
|
|
|
if cert.get('not_before') and cert.get('not_after'):
|
|
|
|
tls_parts.append(f"Valid: {cert['not_before'].split('T')[0]} to {cert['not_after'].split('T')[0]}")
|
|
|
|
if cert.get('version'):
|
|
|
|
tls_parts.append(f"Version: {cert['version']}")
|
|
|
|
if cert.get('serial_number'):
|
|
|
|
tls_parts.append(f"Serial: {cert['serial_number'][:16]}...")
|
|
|
|
|
|
|
|
if tls_parts: # Only add TLS info if we have any parts
|
|
|
|
parts.append(f"{Colors.GREEN}[{' | '.join(tls_parts)}]{Colors.RESET}")
|
|
|
|
|
|
|
|
return ' '.join(parts)
|