<?php

$_SERVER["DOCUMENT_ROOT"] = \realpath(__DIR__);
$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];

class Crack{
    protected static $keyFile = 'DO_NOT_STEAL_OUR_BUS';
    protected static $keyDb = 'thRH4u67fhw87V7Hyr12Hwy0rFr';
    protected static $fileEncRule = 'ET%u%uIS%u%uX%uIR%uT%uI%uB';
    protected static $dbEncRule = 'a%uB%uRa%u%uKa%ud%uA%uBra%u';
    protected $connection = null;

    public function __construct(\mysqli $mysqli){
        $this->connection = $mysqli;
    }

    public function cleanCache(){
        $this->removeDirectory($_SERVER['DOCUMENT_ROOT'] . '/bitrix/stack_cache');
        $this->removeDirectory($_SERVER['DOCUMENT_ROOT'] . '/bitrix/managed_cache');
        $this->removeDirectory($_SERVER['DOCUMENT_ROOT'] . '/bitrix/cache');
    }

    public function apply($date){
        $dbHash = $this->encodeDbCode($date);
        $fileHash = $this->encodeFileCode($date);

        $this->connection->query("UPDATE b_option SET VALUE='$dbHash' WHERE `NAME`='admin_passwordh'");
        \file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/admin/define.php', '<?define("TEMPORARY_CACHE", "' . $fileHash . '");?>');

        $this->cleanCache();
    }

    protected function removeDirectory($dir){
        if(\is_dir($dir)){
            $objects = \scandir($dir);
            foreach($objects as $object){
                if($object != "." && $object != ".."){
                    if (\is_dir($dir."/".$object)){
                        $this->removeDirectory($dir."/".$object);
                    }
                    else{
                        \unlink($dir."/".$object);
                    }

                }
            }
            \rmdir($dir);
        }
    }

    protected function decode(string $string, string $key): string{
        $lk = \strlen($key);
        $raw = \base64_decode($string);

        $counter = 0;
        $decode = '';
        for($i = 0; $i < \strlen($raw); $i++) {
            $decode .= \chr(\ord($raw[$i]) ^ \ord($key[$counter]));
            if($counter == $lk - 1){
                $counter = 0;
            }
            else{
                $counter++;
            }
        }

        return $decode;
    }

    protected function encode(string $string, string $key): string{
        $lk = \strlen($key);

        $encode = '';
        $counter = 0;
        for($i = 0; $i < \strlen($string); $i++){
            $ord = \ord($string[$i]);
            $xor = $ord ^ \ord($key[$counter]);
            $encode .= \chr($xor);

            if($counter == $lk - 1){
                $counter = 0;
            }
            else{
                $counter++;
            }
        }

        return \base64_encode($encode);
    }

    public function decodeFileCode(string $string): array{
        $decode = $this->decode($string, static::$keyFile);

        $result = [
            'decode' => $decode,
            'time' => [
                'hour' => 0,
                'minute' => 0,
                'second' => 0,
                'month' => $decode[6] . $decode[16],
                'day' => $decode[9] . $decode[2],
                'year' => $decode[12] . $decode[7] . $decode[14] . $decode[3]
            ]
        ];

        return $result;
    }

    public function encodeFileCode(string $date): string{
        $decode = \sprintf(static::$fileEncRule, $date[1], $date[9], $date[3], $date[7], $date[0], $date[6], $date[8], $date[4]);

        return $this->encode($decode, static::$keyFile);
    }

    public function decodeDbCode(string $string){
        $decode = $this->decode($string, static::$keyDb);

        $result = [
            'decode' => $decode,
            'time' => [
                'hour' => 0,
                'minute' => 0,
                'second' => 0,
                'month' => $decode[6] . $decode[3],
                'day' => $decode[1] . $decode[14],
                'year' => $decode[10] . $decode[18] . $decode[7] . $decode[12]
            ]
        ];

        return $result;
    }

    public function encodeDbCode(string $date): string{
        $decode = \sprintf(static::$dbEncRule, $date[0], $date[4], $date[3], $date[8], $date[6], $date[9], $date[1], $date[7]);

        return $this->encode($decode, static::$keyDb);
    }
}

$f = $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/admin/define.php';
if(!\file_exists($f)){
    throw new \Exception('File for TEMPORARY_CACHE not found');
}

require_once $f;
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/dbconn.php';
$mysqli = new \mysqli($DBHost, $DBLogin, $DBPassword, $DBName);
if ($mysqli->connect_errno){
    throw new \Exception(\sprintf("Can not connect to DB: %s", $mysqli->connect_error) . \print_r([$DBHost, $DBLogin, $DBPassword, $DBName], true));
}

$crack = new \Crack($mysqli);
$crack->apply(\date('d.m.Y', \strtotime('+365 days')));

\unlink(__FILE__);

echo 'activated';