<?php
// worker.php — FINAL VERIFIED VERSION
// All field names confirmed via Python live testing against real site.
// Flow: Homepage → Login → Upload APK → Poll status → Download & send

if ($argc < 4) {
    die("Usage: php worker.php <chat_id> <apk_path> <caption_base64>\n");
}

$chatId    = $argv[1];
$local_apk = $argv[2];
$caption   = base64_decode($argv[3]);
$orig_name = isset($argv[4]) ? base64_decode($argv[4]) : 'protected.apk'; // Original filename from user

require_once __DIR__ . '/config.php';
$website   = 'https://api.telegram.org/bot' . $botToken;

$safe_chatId = preg_replace('/[^a-zA-Z0-9_\-]/', '', $chatId);
$cookie_file = __DIR__ . '/cookie_'         . md5($chatId . time()) . '.txt';
$flag_file   = __DIR__ . '/heartbeat_flag_' . $safe_chatId . '.lock';

$BASE = 'https://dexprotectx.pro';

sendMessage($chatId, "⚙️ Worker started! Connecting to protection server...");

// ─────────────────────────────────────────────────────────
// STEP 1: Homepage → get JSESSIONID cookie
// ─────────────────────────────────────────────────────────
sendMessage($chatId, "🌐 Step 1/3: Getting session...");
$r1 = dexGet($BASE . '/', $cookie_file);

if ($r1['http_code'] != 200) {
    sendMessage($chatId, "❌ Cannot reach protection server. Please try again later.");
    cleanup($local_apk, $cookie_file, $flag_file);
    exit;
}

// ─────────────────────────────────────────────────────────
// STEP 2: Login  (fields: user + pass + language)
// ─────────────────────────────────────────────────────────
sendMessage($chatId, "🔑 Step 2/3: Logging in...");

dexGet($BASE . '/dex/login', $cookie_file); // seed session

$login_data = http_build_query([
    'user'     => $dex_username,
    'pass'     => $dex_password,
    'language' => 'en_US',
]);

$r2 = dexPost(
    $BASE . '/dex/login',
    $login_data,
    'application/x-www-form-urlencoded',
    $BASE . '/dex/login',
    $cookie_file
);

// Success = redirected away from /login page
$login_ok = (strpos($r2['final_url'], '/login') === false)
          && in_array($r2['http_code'], [200, 302]);

if (!$login_ok) {
    sendMessage($chatId, "❌ Login failed. Please check your credentials in config.php and try again.");
    cleanup($local_apk, $cookie_file, $flag_file);
    exit;
}

sendMessage($chatId, "✅ Login successful!\n\n📤 Step 3/3: Uploading APK...\n⏳ Please wait, this takes 2–5 minutes. I'll ping you every minute!");

// ── Start heartbeat (sends update every 60 sec) ───────────
file_put_contents($flag_file, time());
$hb = escapeshellarg(__DIR__ . '/heartbeat.php');
$hb_chat  = escapeshellarg($chatId);
$hb_token = escapeshellarg($botToken);
$hb_flag  = escapeshellarg($flag_file);
$php = escapeshellarg(PHP_BINARY);
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    pclose(popen("start /B $php $hb $hb_chat $hb_token $hb_flag", "r"));
} else {
    exec("$php $hb $hb_chat $hb_token $hb_flag > /dev/null 2>&1 &");
}

// ─────────────────────────────────────────────────────────
// STEP 3: Upload APK  (multipart, correct field names)
// ─────────────────────────────────────────────────────────
$cFile = new CURLFile($local_apk, 'application/vnd.android.package-archive', basename($local_apk));

// CONFIRMED field names from live form inspection:
$post_data = [
    // File
    'apkFile'          => $cFile,

    // Required hidden/select fields
    'mode'             => 'standard',
    'userModeValue'    => 'false',  // "No" = app STOPS if root/runtime checks fail (strict mode)
    'signatureAlias'   => 'android',

    // Filter textareas — same value for all 3 (user provides via Telegram caption)
    // nativeLibFilters intentionally NOT sent (left blank on server)
    'stringFilters'    => $caption,   // String Encryption filters
    'hideFilters'      => $caption,   // Hide Access filters
    'classFilters'     => $caption,   // Class Encryption filters

    // Build options
    'optimize'         => 'on',
    'stripLogging'     => 'on',
    'crashHandler'     => 'on',

    // Resource protections
    'webViewSupport'   => 'on',
    'manifestMangling' => 'on',
    'assets'           => 'on',
    'res'              => 'on',
    'nameObf'          => 'on',
    'root'             => 'on',
    'strings'          => 'on',

    // Code protections
    'annotationEnc'    => 'on',
    'stringEnc'        => 'on',
    'hideAccess'       => 'on',
    'classEnc'         => 'on',
    'jniObf'           => 'on',
    'nativeLib'        => 'on',

    // Additional protections — ONLY these 2 selected
    'antiEmulator'     => 'on',   // Anti-emulator
    'antiXposed'       => 'on',   // Anti-Xposed
];

$ch = curl_init($BASE . '/dex/protection/options');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => $post_data,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS      => 10,
    CURLOPT_TIMEOUT        => 300,   // increased timeout for large APKs
    CURLOPT_ENCODING       => '',
    CURLOPT_COOKIEFILE     => $cookie_file,
    CURLOPT_COOKIEJAR      => $cookie_file,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_HTTPHEADER     => [
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
        'Accept: text/html,application/xhtml+xml,*/*;q=0.8',
        'Accept-Language: en-US,en;q=0.9',
        'Origin: ' . $BASE,
        'Referer: ' . $BASE . '/dex/protection/options?mode=standard',
        'Sec-Fetch-Site: same-origin',
        'Sec-Fetch-Mode: navigate',
        'Sec-Fetch-Dest: document',
    ],
]);
$upload_body  = curl_exec($ch);
$upload_code  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$upload_url   = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
$upload_error = curl_error($ch);
curl_close($ch);

// Extract process ID from redirect URL e.g. /dex/process/detail?id=3551
preg_match('/process\/detail\?id=(\d+)/', $upload_url, $m);
// Fallback 1: data attribute in HTML body
if (!$m) preg_match('/data-process-id=["\'](\d+)["\']/', $upload_body, $m);
// Fallback 2: hidden input field
if (!$m) preg_match('/<input[^>]+name=["\']processId["\'][^>]+value=["\'](\d+)["\']/', $upload_body, $m);
// Fallback 3: meta refresh redirect
if (!$m) preg_match('/content=["\']\d+;\s*url=.*?process.*?id=(\d+)/i', $upload_body, $m);
// Fallback 4: any href with process detail
if (!$m) preg_match('/href=["\'][^"\']*\/dex\/process\/detail\?id=(\d+)/', $upload_body, $m);
// Fallback 5: JSON response with id field
if (!$m) {
    $json_resp = @json_decode($upload_body, true);
    if ($json_resp && isset($json_resp['id'])) {
        $m = [0, $json_resp['id']];
    } elseif ($json_resp && isset($json_resp['processId'])) {
        $m = [0, $json_resp['processId']];
    }
}

$process_id = isset($m[1]) ? $m[1] : (isset($m[0]) ? $m[0] : null);

if (!$process_id) {
    if (file_exists($flag_file)) unlink($flag_file);
    // Save debug HTML for diagnosis safely
    $debug_file = __DIR__ . '/upload_debug_' . $safe_chatId . '.html';
    file_put_contents($debug_file, $upload_body);
    file_put_contents(__DIR__ . '/upload_response_last.html', $upload_body); // extra backup

    sendMessage($chatId, "❌ Upload failed — could not get process ID from server.\nHTTP Status: $upload_code\nPlease check the server response.");
    cleanup($local_apk, $cookie_file, $flag_file);
    exit;
}

sendMessage($chatId, "📋 APK uploaded! Process started.\n⚙️ Protection is running on server, please wait...");

// ─────────────────────────────────────────────────────────
// STEP 4: Poll /dex/process/detail/data?id=X  (JSON API)
// ─────────────────────────────────────────────────────────
$poll_url   = $BASE . '/dex/process/detail/data?id=' . $process_id;
$detail_url = $BASE . '/dex/process/detail?id='      . $process_id;

$max_wait = 900;  // 15 minutes
$interval = 15;   // poll every 15 seconds
$waited   = 0;
$status   = 'RUNNING';

while ($waited < $max_wait) {
    sleep($interval);
    $waited += $interval;

    $poll_r   = dexGet($poll_url, $cookie_file, $detail_url, true);
    $poll_raw = $poll_r['body'];

    $json = @json_decode($poll_raw, true);
    if ($json && isset($json['status'])) {
        $status = strtoupper($json['status']);
    } else {
        // fallback: HTML
        preg_match('/data-status=["\']([^"\']+)["\']/', $poll_raw, $sm);
        if ($sm) $status = strtoupper($sm[1]);
    }

    if (in_array($status, ['DONE', 'SUCCESS', 'FINISHED', 'COMPLETED'])) {
        break;
    } elseif (in_array($status, ['ERROR', 'FAILED', 'FAILURE'])) {
        if (file_exists($flag_file)) unlink($flag_file);
        sendMessage($chatId, "❌ Protection failed on server. Please try again.");
        cleanup($local_apk, $cookie_file, $flag_file);
        exit;
    }
}

// Stop heartbeat
if (file_exists($flag_file)) unlink($flag_file);

if (!in_array($status, ['DONE', 'SUCCESS', 'FINISHED', 'COMPLETED'])) {
    sendMessage($chatId, "⏰ Timeout — protection is taking too long. Please try again later.");
    cleanup($local_apk, $cookie_file, $flag_file);
    exit;
}

sendMessage($chatId, "🛡️ Protection complete in {$waited}s!\n⬇️ Downloading your protected APK...");

// ─────────────────────────────────────────────────────────
// STEP 5: Get fresh download token & download APK
// ─────────────────────────────────────────────────────────
$detail_r = dexGet($detail_url, $cookie_file);
preg_match(
    '/href=["\']([^"\']*process\/download\?id=' . $process_id . '[^"\']*type=apk[^"\']*)["\']/',
    $detail_r['body'],
    $dl_m
);

if (!$dl_m) {
    sendMessage($chatId, "❌ Could not find the download link. Please try again.");
    cleanup($local_apk, $cookie_file, $flag_file);
    exit;
}

$download_url = $BASE . html_entity_decode($dl_m[1]);

$ch = curl_init($download_url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_TIMEOUT        => 300,
    CURLOPT_ENCODING       => '',
    CURLOPT_COOKIEFILE     => $cookie_file,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_HTTPHEADER     => [
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
        'Accept: application/octet-stream,*/*',
        'Referer: ' . $detail_url,
    ],
]);
$apk_data  = curl_exec($ch);
$dl_code   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$dl_type   = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
curl_close($ch);

$is_apk = (
    strpos($dl_type, 'package-archive') !== false ||
    strpos($dl_type, 'octet-stream')    !== false ||
    strpos($dl_type, 'application/zip') !== false
);

if ($dl_code == 200 && $is_apk && strlen($apk_data) > 10000) {
    // Output file = exact same name as user sent
    // Strip unsafe chars but keep the original name intact
    $safe_name = preg_replace('/[^a-zA-Z0-9._\-]/', '_', $orig_name);
    // Make sure it ends with .apk
    if (strtolower(substr($safe_name, -4)) !== '.apk') {
        $safe_name .= '.apk';
    }
    $out_file = __DIR__ . '/' . $safe_name;
    file_put_contents($out_file, $apk_data);
    $size_kb = round(strlen($apk_data) / 1024);
    sendMessage($chatId, "🛡️ Sending protected APK ({$size_kb} KB)...");
    sendDocument($chatId, $out_file);
    unlink($out_file);
    sendMessage($chatId, "✅ Done! Your protected APK has been sent.");
} else {
    sendMessage($chatId, "❌ Download failed. The server returned an invalid file. Please try again.");
}

cleanup($local_apk, $cookie_file, $flag_file);

// ─────────────────────────────────────────────────────────
// HELPER FUNCTIONS
// ─────────────────────────────────────────────────────────

function baseCurlOpts($cookie_file, $referer = '', $accept_json = false) {
    $headers = [
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
        'Accept-Language: en-US,en;q=0.9',
        'Connection: keep-alive',
        'Sec-Fetch-Site: same-origin',
        'Sec-Fetch-Mode: navigate',
    ];
    if ($accept_json) {
        $headers[] = 'Accept: application/json, text/plain, */*';
    } else {
        $headers[] = 'Accept: text/html,application/xhtml+xml,*/*;q=0.8';
    }
    if ($referer) {
        $headers[] = 'Referer: ' . $referer;
    }
    return [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 10,
        CURLOPT_TIMEOUT        => 60,
        CURLOPT_ENCODING       => '',
        CURLOPT_COOKIEFILE     => $cookie_file,
        CURLOPT_COOKIEJAR      => $cookie_file,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_HTTPHEADER     => $headers,
    ];
}

function dexGet($url, $cookie_file, $referer = '', $json = false) {
    $ch = curl_init($url);
    curl_setopt_array($ch, baseCurlOpts($cookie_file, $referer, $json));
    $body      = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $final_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
    curl_close($ch);
    return ['body' => $body, 'http_code' => $http_code, 'final_url' => $final_url];
}

function dexPost($url, $post_data, $content_type, $referer, $cookie_file) {
    $opts = baseCurlOpts($cookie_file, $referer);
    $opts[CURLOPT_POST]       = true;
    $opts[CURLOPT_POSTFIELDS] = $post_data;
    // Override headers for POST
    $opts[CURLOPT_HTTPHEADER] = [
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
        'Accept: text/html,application/xhtml+xml,*/*;q=0.8',
        'Accept-Language: en-US,en;q=0.9',
        'Content-Type: ' . $content_type,
        'Origin: ' . $GLOBALS['BASE'],
        'Referer: ' . $referer,
        'Sec-Fetch-Site: same-origin',
        'Sec-Fetch-Mode: navigate',
        'Sec-Fetch-Dest: document',
        'Upgrade-Insecure-Requests: 1',
    ];
    $ch = curl_init($url);
    curl_setopt_array($ch, $opts);
    $body      = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $final_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
    curl_close($ch);
    return ['body' => $body, 'http_code' => $http_code, 'final_url' => $final_url];
}

function sendMessage($chatId, $message) {
    global $website;
    $url = $website . "/sendMessage";
    $post_data = ['chat_id' => $chatId, 'text' => $message];
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($post_data),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_TIMEOUT => 30
    ]);
    curl_exec($ch);
    curl_close($ch);
}

function sendDocument($chatId, $filePath) {
    global $website;
    $ch = curl_init($website . "/sendDocument");
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => ['chat_id' => $chatId, 'document' => new CURLFile($filePath)],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_TIMEOUT        => 300,
    ]);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

function cleanup($apk, $cookie, $flag = '') {
    if (file_exists($apk))           unlink($apk);
    if (file_exists($cookie))        unlink($cookie);
    if ($flag && file_exists($flag)) unlink($flag);
}
?>
