httpz

- Hyper-fast HTTP Scraping Tool
git clone git://git.acid.vegas/httpz.git
Log | Files | Refs | Archive | README | LICENSE

formatters.py (4860B)

      1 #!/usr/bin/env python3
      2 # HTTPZ Web Scanner - Developed by acidvegas in Python (https://github.com/acidvegas/httpz)
      3 # httpz_scanner/formatters.py
      4 
      5 from .colors import Colors
      6 from .utils  import human_size
      7 
      8 
      9 def format_console_output(result: dict, debug: bool = False, show_fields: dict = None, match_codes: set = None, exclude_codes: set = None) -> str:
     10     '''
     11     Format the output with colored sections
     12     
     13     :param result: Dictionary containing domain check results
     14     :param debug: Whether to show error states
     15     :param show_fields: Dictionary of fields to show
     16     :param match_codes: Set of status codes to match
     17     :param exclude_codes: Set of status codes to exclude
     18     '''
     19     if result['status'] < 0 and not debug:
     20         return ''
     21         
     22     if match_codes and result['status'] not in match_codes:
     23         return ''
     24     if exclude_codes and result['status'] in exclude_codes:
     25         return ''
     26 
     27     parts = []
     28     
     29     # Status code
     30     if show_fields.get('status_code'):
     31         if result['status'] < 0:
     32             status = f"{Colors.RED}[{result['status']}]{Colors.RESET}"
     33         elif 200 <= result['status'] < 300:
     34             status = f"{Colors.GREEN}[{result['status']}]{Colors.RESET}"
     35         elif 300 <= result['status'] < 400:
     36             status = f"{Colors.YELLOW}[{result['status']}]{Colors.RESET}"
     37         else:
     38             status = f"{Colors.RED}[{result['status']}]{Colors.RESET}"
     39         parts.append(status)
     40     
     41     # Domain/URL
     42     parts.append(f"[{result['url']}]")
     43     
     44     # Content Type
     45     if show_fields.get('content_type') and result.get('content_type'):
     46         parts.append(f"{Colors.CYAN}[{result['content_type']}]{Colors.RESET}")
     47     
     48     # Content Length
     49     if show_fields.get('content_length') and result.get('content_length'):
     50         parts.append(f"{Colors.PINK}[{result['content_length']}]{Colors.RESET}")
     51     
     52     # Title
     53     if show_fields.get('title') and result.get('title'):
     54         parts.append(f"{Colors.DARK_GREEN}[{result['title']}]{Colors.RESET}")
     55     
     56     # Body preview
     57     if show_fields.get('body') and result.get('body'):
     58         body = result['body'][:100] + ('...' if len(result['body']) > 100 else '')
     59         parts.append(f"{Colors.BLUE}[{body}]{Colors.RESET}")
     60     
     61     # IPs
     62     if show_fields.get('ip') and result.get('ips'):
     63         ips_text = ', '.join(result['ips'])
     64         parts.append(f"{Colors.YELLOW}[{ips_text}]{Colors.RESET}")
     65 
     66     # Favicon hash
     67     if show_fields.get('favicon') and result.get('favicon_hash'):
     68         parts.append(f"{Colors.PURPLE}[{result['favicon_hash']}]{Colors.RESET}")
     69 
     70     # Headers
     71     if show_fields.get('headers') and result.get('response_headers'):
     72         headers_text = [f"{k}: {v}" for k, v in result['response_headers'].items()]
     73         parts.append(f"{Colors.CYAN}[{', '.join(headers_text)}]{Colors.RESET}")
     74     else:
     75         if show_fields.get('content_type') and result.get('content_type'):
     76             parts.append(f"{Colors.HEADER}[{result['content_type']}]{Colors.RESET}")
     77         
     78         if show_fields.get('content_length') and result.get('content_length'):
     79             try:
     80                 size = human_size(int(result['content_length']))
     81                 parts.append(f"{Colors.PINK}[{size}]{Colors.RESET}")
     82             except (ValueError, TypeError):
     83                 parts.append(f"{Colors.PINK}[{result['content_length']}]{Colors.RESET}")
     84 
     85     # Redirect Chain
     86     if show_fields.get('follow_redirects') and result.get('redirect_chain'):
     87         chain = ' -> '.join(result['redirect_chain'])
     88         parts.append(f"{Colors.YELLOW}[Redirects: {chain}]{Colors.RESET}")
     89 
     90     # CNAME
     91     if show_fields.get('cname') and result.get('cname'):
     92         parts.append(f"{Colors.PURPLE}[CNAME: {result['cname']}]{Colors.RESET}")
     93     
     94     # TLS Certificate Info
     95     if show_fields.get('tls') and result.get('tls'):
     96         cert = result['tls']
     97         tls_parts = []
     98         if cert.get('common_name'):
     99             tls_parts.append(f"Subject: {cert['common_name']}")
    100         if cert.get('issuer'):
    101             tls_parts.append(f"Issuer: {cert['issuer']}")
    102         if cert.get('fingerprint'):
    103             tls_parts.append(f"Fingerprint: {cert['fingerprint'][:16]}...")
    104         if cert.get('alt_names'):
    105             tls_parts.append(f"SANs: {', '.join(cert['alt_names'][:3])}")
    106         if cert.get('not_before') and cert.get('not_after'):
    107             tls_parts.append(f"Valid: {cert['not_before'].split('T')[0]} to {cert['not_after'].split('T')[0]}")
    108         if cert.get('version'):
    109             tls_parts.append(f"Version: {cert['version']}")
    110         if cert.get('serial_number'):
    111             tls_parts.append(f"Serial: {cert['serial_number'][:16]}...")
    112         
    113         if tls_parts:  # Only add TLS info if we have any parts
    114             parts.append(f"{Colors.GREEN}[{' | '.join(tls_parts)}]{Colors.RESET}")
    115 
    116     return ' '.join(parts)