#!/usr/bin/env python3
"""Agent for testing deep link / custom URL scheme vulnerabilities in mobile apps."""

import argparse
import json
import re
import subprocess
from datetime import datetime, timezone


ANDROID_SCHEME_PATTERN = re.compile(
    r'<intent-filter[^>]*>.*?<data\s+android:scheme="([^"]+)".*?</intent-filter>',
    re.DOTALL
)
ANDROID_HOST_PATTERN = re.compile(r'android:host="([^"]+)"')

IOS_SCHEME_PATTERN = re.compile(r'<string>(\w+)</string>\s*</array>\s*<key>CFBundleURLName')
IOS_UNIVERSAL_PATTERN = re.compile(r'"applinks:\s*([\w.-]+)"')


def analyze_android_manifest(manifest_path):
    """Parse AndroidManifest.xml for deep link configurations."""
    findings = []
    try:
        with open(manifest_path, "r", errors="replace") as f:
            content = f.read()
    except FileNotFoundError:
        return findings

    for match in ANDROID_SCHEME_PATTERN.finditer(content):
        block = match.group(0)
        scheme = match.group(1)
        hosts = ANDROID_HOST_PATTERN.findall(block)
        exported = "android:exported=\"true\"" in block or "android:exported" not in block
        findings.append({
            "scheme": scheme,
            "hosts": hosts,
            "exported": exported,
            "block": block[:200],
            "risk": "HIGH" if exported and scheme not in ("https", "http") else "MEDIUM",
        })
    return findings


def analyze_ios_plist(plist_path):
    """Parse iOS Info.plist for URL scheme and universal link configurations."""
    findings = []
    try:
        with open(plist_path, "r", errors="replace") as f:
            content = f.read()
    except FileNotFoundError:
        return findings

    for match in IOS_SCHEME_PATTERN.finditer(content):
        findings.append({
            "type": "custom_url_scheme",
            "scheme": match.group(1),
            "risk": "HIGH",
            "note": "Custom URL schemes lack origin verification",
        })

    for match in IOS_UNIVERSAL_PATTERN.finditer(content):
        findings.append({
            "type": "universal_link",
            "domain": match.group(1),
            "risk": "LOW",
            "note": "Universal links verify domain ownership",
        })
    return findings


def test_deep_link_injection(scheme, host, path, payload):
    """Construct and test a deep link injection payload."""
    test_url = f"{scheme}://{host}{path}{payload}"
    return {
        "test_url": test_url,
        "payload": payload,
        "vectors": [
            "Open redirect via deep link",
            "JavaScript execution in WebView",
            "Parameter injection",
            "Intent redirection (Android)",
        ],
    }


def check_adb_deep_link(package, uri):
    """Test Android deep link via ADB."""
    cmd = ["adb", "shell", "am", "start", "-W",
           "-a", "android.intent.action.VIEW",
           "-d", uri, package]
    try:
        result = subprocess.check_output(cmd, text=True, errors="replace", timeout=15)
        return {"uri": uri, "status": "launched", "output": result[:300]}
    except (subprocess.SubprocessError, FileNotFoundError):
        return {"uri": uri, "status": "failed"}


def main():
    parser = argparse.ArgumentParser(
        description="Test deep link / URL scheme vulnerabilities (authorized testing only)"
    )
    parser.add_argument("--android-manifest", help="Path to AndroidManifest.xml")
    parser.add_argument("--ios-plist", help="Path to Info.plist")
    parser.add_argument("--test-scheme", help="URL scheme to test")
    parser.add_argument("--test-host", help="Host for deep link test")
    parser.add_argument("--output", "-o", help="Output JSON report")
    args = parser.parse_args()

    print("[*] Deep Link Vulnerability Testing Agent")
    report = {"timestamp": datetime.now(timezone.utc).isoformat(), "findings": []}

    if args.android_manifest:
        android = analyze_android_manifest(args.android_manifest)
        report["findings"].extend(android)
        print(f"[*] Android deep links found: {len(android)}")

    if args.ios_plist:
        ios = analyze_ios_plist(args.ios_plist)
        report["findings"].extend(ios)
        print(f"[*] iOS URL schemes found: {len(ios)}")

    if args.test_scheme and args.test_host:
        payloads = [
            "?redirect=https://evil.com",
            "#javascript:alert(1)",
            "?token=stolen&callback=https://evil.com",
            "/../../sensitive-path",
        ]
        for p in payloads:
            result = test_deep_link_injection(args.test_scheme, args.test_host, "/", p)
            report["findings"].append(result)

    report["risk_level"] = "HIGH" if report["findings"] else "LOW"

    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2)
        print(f"[*] Report saved to {args.output}")
    else:
        print(json.dumps(report, indent=2))


if __name__ == "__main__":
    main()
