# -*- coding: utf-8 -*-
import requests
import subprocess
import os
import threading
from urllib.parse import urljoin
from concurrent.futures import ThreadPoolExecutor
from colorama import Fore, Style, init
import ctypes
from urllib.parse import urlparse

init(autoreset=True)

def set_cmd_title(title):
    try:
        ctypes.windll.kernel32.SetConsoleTitleW(title)
    except:
        pass

def clear_screen():
    try:
        subprocess.call("cls", shell=True)
    except:
        try:
            subprocess.call("clear", shell=True)
        except:
            print("\n" * 50)

clear_screen()
set_cmd_title("Env Scanner")

X = Fore.LIGHTMAGENTA_EX
N = Style.DIM
XX = Style.BRIGHT
O = Style.RESET_ALL

requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

MAX_FILE_SIZE = 10 * 1024 * 1024
current_file_index = 1
current_filename = "vulnerable.txt"
file_lock = threading.Lock()

banner = '''

        ██╗      █████╗ ██████╗  █████╗ 
        ██║     ██╔══██╗██╔══██╗██╔══██╗
        ██║     ███████║██████╔╝███████║
        ██║     ██╔══██║██╔══██╗██╔══██║
        ███████╗██║  ██║██║  ██║██║  ██║
        ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝
           Coded by @F0X_6T9

'''

paths = [
    "/.env", "/conf/.env", "/wp-content/.env", "/wp-admin/.env", "/library/.env",
    "/new/.env", "/vendor/.env", "/old/.env", "/local/.env", "/api/.env", "/blog/.env",
    "/crm/.env", "/admin/.env", "/laravel/.env", "/app/.env", "/app/config/.env",
    "/apps/.env", "/audio/.env", "/cgi-bin/.env", "/backend/.env", "/src/.env",
    "/base/.env", "/core/.env", "/vendor/laravel/.env", "/storage/.env", "/protected/.env",
    "/newsite/.env", "/www/.env", "/sites/all/libraries/mailchimp/.env", "/database/.env",
    "/public/.env", "/__tests__/test-become/.env", "/redmine/.env", "/gists/cache",
    "/uploads/.env", "/lib/.env", "/sendgrid.env", "/aws.env", "/.env.example",
    "/main/.env", "/docs/.env", "/client/.env", "/.env.dev", "/blogs/.env", "/shared/.env",
    "/download/.env", "/.env.php", "/site/.env", "/sites/.env", "/web/.env"
]

def is_vulnerable(response_text):
    env_indicators = ['APP_NAME', 'APP_KEY', 'DB_', 'API_', 'SECRET_', 'PASSWORD', 'DATABASE_URL', 'MAIL_', 'REDIS_', 'AWS_', 'CLOUD_', 'ENCRYPTION_KEY', 'PRIVATE_KEY']
    return any(indicator in response_text for indicator in env_indicators)

def get_next_filename():
    global current_file_index
    if current_file_index == 1:
        return "vulnerable.txt"
    else:
        return f"vulnerable{current_file_index}.txt"

def rotate_file():
    global current_file_index, current_filename
    
    with file_lock:
        if os.path.exists(current_filename):
            try:
                os.remove(current_filename)
                print(Fore.YELLOW + f"[*] Deleted {current_filename}" + O)
            except Exception:
                pass
        
        current_file_index += 1
        current_filename = get_next_filename()
        open(current_filename, 'a', encoding='utf-8').close()
        print(Fore.GREEN + f"[+] Created new file: {current_filename}" + O)

def save_vulnerable_domain(domain, full_url):
    global current_filename
    
    with file_lock:
        if os.path.exists(current_filename):
            file_size = os.path.getsize(current_filename)
            if file_size >= MAX_FILE_SIZE:
                print(Fore.YELLOW + f"[!] File {current_filename} reached {MAX_FILE_SIZE/1024/1024}MB, rotating..." + O)
                rotate_file()
        
        try:
            with open(current_filename, "a", encoding='utf-8') as file:
                file.write(f"{full_url}\n")
        except Exception:
            pass

def check_url(session, full_url):
    try:
        response = session.get(full_url, verify=False, timeout=10)
        if response.status_code == 200 and is_vulnerable(response.text):
            domain = urlparse(full_url).netloc
            print(Fore.LIGHTGREEN_EX + f"[+] Vulnerable URL: {Fore.WHITE}{domain} - {full_url}" + O)
            save_vulnerable_domain(domain, full_url)
            return True
        return False
    except Exception:
        return False

def process_url(base_url):
    base_url = base_url.strip()
    if not base_url:
        return
        
    if not base_url.startswith(("http://", "https://")):
        base_url = "http://" + base_url
        
    with requests.Session() as session:
        session.headers.update({'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'})
        
        vulnerable_found = False
        for path in paths:
            if vulnerable_found:
                break
            full_url = urljoin(base_url, path)
            if check_url(session, full_url):
                vulnerable_found = True
                break
        
        if not vulnerable_found:
            domain = urlparse(base_url).netloc
            print(Fore.LIGHTMAGENTA_EX + f"[-] Not vulnerable: {Fore.WHITE}{domain}" + O)

def main():
    try:
        global current_filename
        open(current_filename, 'a', encoding='utf-8').close()
        
        print(Fore.CYAN + f"[*] Max file size: {MAX_FILE_SIZE/1024/1024}MB" + O)
        print(banner)
        xtt_file_path = input(f"{X}{N}{XX} List: " + O).strip()
        
        if not xtt_file_path:
            print(Fore.RED + "[-] No file path provided!" + O)
            return
            
        with open(xtt_file_path, "r", encoding='utf-8') as xtt_file:
            urls = [line.strip() for line in xtt_file if line.strip()]
            
        if not urls:
            print(Fore.RED + "[-] No URLs found in the file!" + O)
            return
            
        print(Fore.CYAN + f"[*] Processing {len(urls)} URLs with {len(paths)} paths each..." + O)
        print(Fore.YELLOW + "[*] Starting scan..." + O)
        print(Fore.CYAN + f"[*] Current output file: {current_filename}" + O)
        
        with ThreadPoolExecutor(max_workers=50) as executor:
            list(executor.map(process_url, urls))
            
        print(Fore.GREEN + "[+] Scan completed!" + O)
        print(Fore.GREEN + "[+] Results saved in: " + O)
        
        # Display all result files
        index = 1
        while True:
            if index == 1:
                filename = "vulnerable.txt"
            else:
                filename = f"vulnerable{index}.txt"
                
            if os.path.exists(filename):
                file_size = os.path.getsize(filename)
                if file_size > 0:
                    print(Fore.GREEN + f"    - {filename} ({file_size} bytes)" + O)
            else:
                break
            index += 1
            
        print(Fore.GREEN + "[+] All done!" + O)
        
    except FileNotFoundError:
        print(Fore.RED + f"[-] File not found: {xtt_file_path}" + O)
    except KeyboardInterrupt:
        print(Fore.YELLOW + "\n[!] Scan interrupted by user!" + O)
    except Exception as e:
        print(Fore.RED + f"[-] Error: {str(e)}" + O)

if __name__ == "__main__":
    main()