<?php
if (!function_exists('aqua_encode')) {
function aqua_encode($method, $code) {
    $code = aqua_strip_php($code);
    if ($code === '') { throw new InvalidArgumentException('empty'); }
    switch ($method) {
        case 'whitespace': $out = aqua_enc_whitespace($code); break;
        case 'base64':     $out = aqua_enc_base64($code); break;
        case 'gzinflate':  $out = aqua_enc_gzinflate($code); break;
        case 'hex2bin':    $out = aqua_enc_hex2bin($code); break;
        case 'goto':       $out = aqua_enc_goto($code); break;
        case 'chunk':      $out = aqua_enc_chunk($code); break;
        default: throw new InvalidArgumentException("unknown '$method'");
    }
    return $out;
}

function aqua_strip_php($code) {
    $code = trim($code);
    if (strncmp($code, '<?php', 5) === 0) $code = substr($code, 5);
    elseif (strncmp($code, '<?', 2) === 0) $code = substr($code, 2);
    if (substr($code, -2) === '?>') $code = substr($code, 0, -2);
    return trim($code);
}
function aqua_enc_base64($code) {
    return "eval(base64_decode('" . base64_encode($code) . "'));";
}

function aqua_enc_hex2bin($code) {
    return "eval(hex2bin('" . bin2hex($code) . "'));";
}

function aqua_enc_gzinflate($code) {
    $z = @gzdeflate($code, 9);
    if ($z === false) {
        // 没 zlib,退回 base64
        return aqua_enc_base64($code);
    }
    return "eval(gzinflate(base64_decode('" . base64_encode($z) . "')));";
}
function aqua_enc_whitespace($code) {
    $ws = '';
    $len = strlen($code);
    for ($i = 0; $i < $len; $i++) {
        $b = ord($code[$i]);
        for ($j = 7; $j >= 0; $j--) {
            $ws .= (($b >> $j) & 1) ? "\t" : ' ';
        }
    }
    $enc = base64_encode($ws); 
    return "eval((function(\$s){\$s=base64_decode(\$s);\$o='';for(\$i=0,\$n=strlen(\$s);\$i<\$n;\$i+=8){\$b=0;for(\$j=0;\$j<8;\$j++){\$b=(\$b<<1)|(\$s[\$i+\$j]==\"\\t\"?1:0);}\$o.=chr(\$b);}return \$o;})('" . $enc . "'));";
}

function aqua_enc_chunk($code) {
    $b64 = base64_encode($code);
    $n = strlen($b64);
    $parts = array();
    $pos = 0;
    while ($pos < $n) {
        $len = mt_rand(8, 24);
        if ($pos + $len > $n) $len = $n - $pos;
        $parts[] = "'" . substr($b64, $pos, $len) . "'";
        $pos += $len;
    }
    return "eval(base64_decode(" . implode('.', $parts) . "));";
}

function aqua_enc_goto($code) {
    $payload = base64_encode($code);
    $labels = array();
    for ($i = 0; $i < 6; $i++) {
        $labels[] = 'L_' . aqua_rand_ident(6);
    }
    list($La, $Lb, $Lc, $Ld, $Le, $Lend) = $labels;
    $var = '$' . aqua_rand_ident(4);

    $stmts = array();
    $stmts[$Lb]   = "$Lb: eval($var); goto $Lend;";
    $stmts[$La]   = "$La: $var = base64_decode('$payload'); goto $Lc;";
    $stmts[$Le]   = "$Le: goto $Lb;";
    $stmts[$Lc]   = "$Lc: goto $Ld;";
    $stmts[$Ld]   = "$Ld: goto $Le;";
    $stmts[$Lend] = "$Lend:;";

    $keys = array($Lb, $La, $Le, $Lc, $Ld, $Lend);
    shuffle($keys);

    $body = "goto $La; ";
    foreach ($keys as $k) {
        $body .= $stmts[$k] . ' ';
    }

    return "eval(" . var_export($body, true) . ");";
}

function aqua_rand_ident($len) {
    $chars = 'abcdefghijklmnopqrstuvwxyz';
    $s = '';
    for ($i = 0; $i < $len; $i++) {
        $s .= $chars[mt_rand(0, 25)];
    }
    return $s;
}

} 
