<?php

session_start();
set_time_limit(120);
if (!ini_set('default_charset', '')) {
  echo "could not set default_charset to utf-8<br>";
  exit(1);
}

require("CookiesManager.php");

class Proxy
{
    private $THIS_URL            = "";
    private $THIS_DOMAIN         = "";
    public $TARGET_URL          = "";
    private $PATH                = "";
    private $PATHACCS            = "";
    private $aMember_apikey = "";
    private $cacheFiles = ["png","jpg","gif","tiff","woff","woff2","ttf","ico","svg","js","css","scss","map"];
    private $aMember_url = "";
    private $cfbypassProxy = "";
    private $csvLimit = 2000;
    private $csvLimitTotal = 100; // maximum exports until delete
    private $byGet = false;
    private $proxies = "";
    private $fakeToken = "d9ekdq2xDk3ke0kEOFkjopascm3423pky1";
    private $fakeEmail = "********@gmail.com";

    private $blacklistPaths = ["/cdn-cgi/challenge-platform","/account","/user/logout","/user/logout|/account/members","/plans-pricing" ,
        "/rank-tracker","/user/alerts/backlinks", "/new-project", "/site-audit","/competitive-analysis","/web-explorer","/dashboard","/account/applications"];
    private $blacklistUrls = ["https://www.googleadservices.com","https://www.google.com","https://google.com","https://www.youtube.com","https://youtube.com","https://m.stripe.com","https://www.stripe.com","https://stripe.com","https://googleads.g.doubleclick.net","https://www.google.com","https://www.google.nl", "https://connect.facebook.net", "https://www.facebook.com","https://cdnjs.cloudflare.com","https://www.google-analytics.com","https://q.quora.com","https://va.tawk.to","ftcguardian.com","q.stripe.com","https://q.stripe.com", "wistia.com"];

    /**
     * Your private auth key. It is recommended to change it.
     * If you installed the package via composer, call `Proxy::$AUTH_KEY = '<your-new-key>';` before running the proxy.
     * If you copied this file, change the value here in place.
     * @var string
     */
    public $AUTH_KEY = 'Bj5pnZEX6DkcG6Nz6AjDUT1bvcGRVhRaXDuKDX9CjsEs2';

    /**
     * Set this to false to disable authorization. Useful for debugging, not recommended in production.
     * @var bool
     */
    public $ENABLE_AUTH = false;

    /**
     * If true, PHP safe mode compatibility will not be checked
     * (you may not need it if no POST files are sent over proxy)
     * @var bool
     */
    public $IGNORE_SAFE_MODE = false;

    /**
     * Enable debug mode (you can do it by sending Proxy-Debug header as well).
     * This value overrides any value specified in Proxy-Debug header.
     * @var bool
     */
    public $DEBUG = false;

    /**
     * When set to false the fetched header is not included in the result
     * @var bool
     */
    public $CURLOPT_HEADER = true;

    /**
     * When set to false the fetched result is echoed immediately instead of waiting for the fetch to complete first
     * @var bool
     */
    public $CURLOPT_RETURNTRANSFER = true;

    /**
     * Name of remote debug header
     * @var string
     */
    public $HEADER_HTTP_PROXY_DEBUG = 'HTTP_PROXY_DEBUG';

    /**
     * Name of the proxy auth key header
     * @var string
     */
    public $HEADER_HTTP_PROXY_AUTH = 'HTTP_PROXY_AUTH';

    /**
     * Name of the target url header
     * @var string
     */
    public $HEADER_HTTP_PROXY_TARGET_URL = 'HTTP_PROXY_TARGET_URL';

    /**
     * Line break for debug purposes
     * @var string
     */
    protected $HR = PHP_EOL . PHP_EOL . '----------------------------------------------' . PHP_EOL . PHP_EOL;

    public function __construct() {
      $config = json_decode(file_get_contents("./config.json"));

      $this->THIS_URL            = $config->url;
      $this->THIS_DOMAIN         = $config->domain;
      $this->TARGET_URL          = $config->target;
      $this->PATH                = $config->path;
      $this->PATHACCS            = $config->pathaccs;
      $this->aMember_apikey = $config->amemberApi;
      $this->aMember_url = $config->amemberUrl;
      $this->cfbypassProxy = $config->cfbypassProxy;
      $this->proxies = $this->getProxies(); // $config->proxies
      if (isset($config->debug))
        $this->DEBUG = $config->debug;
    }
    /**
     * @return string[]
     */
    protected function getSkippedHeaders()
    {
        return [
            $this->HEADER_HTTP_PROXY_TARGET_URL,
            $this->HEADER_HTTP_PROXY_AUTH,
            $this->HEADER_HTTP_PROXY_DEBUG,
            'HTTP_HOST',
            'HTTP_ACCEPT_ENCODING'
        ];
    }

    /**
     * Return variable or default value if not set
     * @param mixed $variable
     * @param mixed|null $default
     * @return mixed
     * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection
     */
    protected function ri(&$variable, $default = null)
    {
        if (isset($variable)) {
            return $variable;
        } else {
            return $default;
        }
    }

    /**
     * @param string $message
     */
    protected function exitWithError($message)
    {
        http_response_code(500);
        echo 'PROXY ERROR: ' . $message;
        exit(500);
    }

    /**
     * @return bool
     */
    public function isInstalledWithComposer()
    {
        $autoloaderPath = join(DIRECTORY_SEPARATOR, [dirname(dirname(__DIR__)), 'autoload.php']);
        return is_readable($autoloaderPath);
    }

    /**
     * @return void
     */
    public function registerErrorHandlers()
    {
        set_error_handler(function ($code, $message, $file, $line) {
            Proxy::exitWithError("($code) $message in $file at line $line");
        }, E_ALL);
/*
        set_exception_handler(function (Exception $ex) {
            Proxy::exitWithError("{$ex->getMessage()} in {$ex->getFile()} at line {$ex->getLine()}");
        });*/
    }

    /**
     * @return void
     */
    public function checkCompatibility()
    {
        if (!$this->IGNORE_SAFE_MODE && function_exists('ini_get') && ini_get('safe_mode')) {
            throw new RuntimeException('Safe mode is enabled, this may cause problems with uploading files');
        }

        if (!function_exists('curl_init')) {
            throw new RuntimeException('libcurl is not installed on this server');
        }

        if (!function_exists('gzdecode')) {
            throw new RuntimeException('gzip is not installed on this server');
        }
    }

    /**
     * @return bool
     */
    protected function hasCURLFileSupport()
    {
        return class_exists('CURLFile');
    }

    /**
     * @param string $headerString
     * @return string[]
     */
    protected function splitResponseHeaders($headerString)
    {
        $results = [];
        $headerLines = preg_split('/[\r\n]+/', $headerString);
        foreach ($headerLines as $headerLine) {
            if (empty($headerLine)) {
                continue;
            }

            // Header contains HTTP version specification and path
            if (strpos($headerLine, 'HTTP/') === 0) {
                // Reset the output array as there may by multiple response headers
                $results = [];
                continue;
            }

            $results[] = "$headerLine";
        }

        return $results;
    }

    /**
     * Returns true if response code matches 2xx or 3xx
     * @param int $responseCode
     * @return bool
     */
    public function isResponseCodeOk($responseCode)
    {
        return preg_match('/^[23]\d\d$/', $responseCode) === 1;
    }

    public function publicUrl($isroot = false) {
      $allexp = explode("/",$_SERVER['REQUEST_URI']);
      $sub = $allexp[1];
      if ($sub == "" && count($allexp) > 2)
        return "https:".$_SERVER['REQUEST_URI'];
      // Allow only this subdomains
      if (!in_array($sub, Array("_www", "_analytics", "_cdn", "_re-cdn", "_app", "_gtm", "_static-app"))) {
        $sub = "";
      }

      $rest = $sub && $sub != '' ? preg_replace("/^\/".$sub."/", "", $_SERVER['REQUEST_URI']) : $_SERVER['REQUEST_URI'];

      if ($sub == "_gtm") {
        return "https://www.googletagmanager.com".$rest;
      } elseif ($isroot) {
        return "https://".($sub && $sub != '' ? str_replace("_","",$sub)."." : "app.").$this->TARGET_URL."/";
      } else {
        return "https://".($sub && $sub != '' ? str_replace("_","",$sub)."." : "app.").$this->TARGET_URL.$rest;
      }
    }
    /**
     * @return string
     */
    protected function getTargetUrl()
    {
        if (!empty($this->TARGET_URL)) {
            $targetURL = $this->publicUrl();
        } else {
            $targetURL = $this->ri($_SERVER[$this->HEADER_HTTP_PROXY_TARGET_URL]);
        }

        if (empty($targetURL)) {
            throw new RuntimeException($this->HEADER_HTTP_PROXY_TARGET_URL . ' header is empty');
        }

        if (filter_var($targetURL, FILTER_VALIDATE_URL) === false) {
            throw new RuntimeException($this->HEADER_HTTP_PROXY_TARGET_URL . ' "' . $targetURL . '" is invalid');
        }

        return $targetURL;
    }
    function getProxies() {
      return json_decode(file_get_contents($this->PATH."/proxies.json"));
    }

    function delProxy($proxy) {
      $proxies = getProxies();
      $reProxies = [];
      foreach($proxies as $prox) {
        if ($proxy != $prox)
          $reProxies[] = $prox;
      }
      file_put_contents($this->PATH."/proxies.json", json_encode($reProxies));
    }
    /**
     * @return bool
     */
    protected function isDebug()
    {
        return $this->DEBUG;
    }

    /**
     * @return bool
     */
    protected function isAuthenticated()
    {
        return !$this->ENABLE_AUTH || $this->ri($_SERVER[$this->HEADER_HTTP_PROXY_AUTH]) === $this->AUTH_KEY;
    }

    /**
     * @param string[] $skippedHeaders
     * @return string[]
     */
    protected function getIncomingRequestHeaders($skippedHeaders = [])
    {
        $results = [];
        $headers = getallheaders();
        foreach ($headers as $key => $value) {
            if (in_array($key, $skippedHeaders)) {
                continue;
            }
            $results[] = "$key: $value";
        }

        return $results;
    }
    /*
    protected function getIncomingRequestHeaders($skippedHeaders = [])
    {
        $results = [];
        foreach ($_SERVER as $key => $value) {
            if (in_array($key, $skippedHeaders)) {
                continue;
            }

            $loweredKey = strtolower($key);
            if (strpos($loweredKey, 'http_') === 0) {
                // Remove prefix
                $key = substr($loweredKey, strlen('http_'));
                // Replace underscores with dashes
                $key = str_replace('_', '-', $key);
                // Capital each word
                $key = ucwords($key, '-');

                $results[] = "$key: $value";
            }
        }

        return $results;
    }
    */

    public function fixUrl($target, $path) {
      $spl = explode("/", $this->THIS_URL);
      if (count($spl) > 3 && $spl[3] != "") {
        return $target.str_replace("/".$spl[3]."/", "", $path);
      } else {
        return substr($target, 0, -1).$path;
      }
    }

    public function slugify($text){
      // replace non letter or digits by -
      $text = preg_replace('~[^\pL\d]+~u', '-', $text);

      // transliterate
      $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);

      // remove unwanted characters
      $text = preg_replace('~[^-\w]+~', '', $text);

      // trim
      $text = trim($text, '-');

      // remove duplicated - symbols
      $text = preg_replace('~-+~', '-', $text);

      // lowercase
      $text = strtolower($text);

      if (empty($text)) {
        return 'n-a';
      }

      return md5($text);
    }

    public function saveCache($url, $content) {
      $bypassurl = (strstr($url, "/isauth") || strstr($url, "/api/v1/users/authenticate") || strstr($url, "/api/v1/users/initial_authentication")) ? true : false;
      if ($bypassurl)
        return false;
      $cachefile = explode("?", $url)[0];
      /*
      $aPostParams = $this->cleanInput(file_get_contents('php://input'));
      if ($aPostParams && $aPostParams != "" && $this->isJson($aPostParams)) {
        $aPostParams = json_decode($aPostParams, true);
        $cachefile .= "_".http_build_query($aPostParams);
      } elseif (count($_GET)) {
        $cachefile .= "_".http_build_query($_GET);
      }
      */

      $cachefile = $this->PATH."cache/".$this->slugify($cachefile).".json";
      $date = time();
      file_put_contents($cachefile, $content);
    }

    public function hasCache($url) {
      // BYPASS CERTAIN URLS?????
      //$cachefile = $url;
      $cachefile = explode("?", $url)[0];
      /*
      $aPostParams = $this->cleanInput(file_get_contents('php://input'));
      if ($aPostParams && $aPostParams != "" && $this->isJson($aPostParams)) {
        $aPostParams = json_decode($aPostParams, true);
        $cachefile .= "_".http_build_query($aPostParams);
      } elseif (count($_GET)) {
        $cachefile .= "_".http_build_query($_GET);
      }
      */

      $cachefile = $this->PATH."cache/".$this->slugify($cachefile).".json";
      if (file_exists($cachefile)) {
        $this->cacheControl($cachefile);
        $cache = file_get_contents($cachefile);
        return $cache;
      } else {
        return false;
      }
    }

    public function randProxy($not = null) {
      if ($not) {
        $picked;
        do {
          $picked = $this->proxies[array_rand($this->proxies)];
        } while(!$picked || $not == $picked);
        return $picked;
      } else {
        return $this->proxies[array_rand($this->proxies)];
      }
    }
    /*
      ACCOUNTS
    */
    public function listAccount() {
      $d = dir($this->PATHACCS);
      $accs = Array();
      while(false !== ($entry = $d->read())) {
        if (strstr($entry, "account_"))
          $accs[] = $entry;
      }
      $d->close();
      return $accs;
    }

    public function getAccount($id) {
      $accs = $this->listAccount();
      return $accs[$id];
    }

    public function getAccountFile($acc, $file) {
      $filepath = $this->PATHACCS.$acc."/".$file;
      try {
        if (file_exists($filepath)) {
          $filedata = trim(file_get_contents($filepath));
          if (strstr($file, ".json")) {
            return json_decode($filedata);
          } else {
            return $filedata;
          }
        }
        return false;
      } catch (exception $e) {
        $this->doLog($filepath." Error parsing: ".$e->getMessage());
        return false;
      }
    }

    public function saveAccountFile($acc, $file, $data) {
      $filepath = $this->PATHACCS.$acc."/".$file.".json";
      file_put_contents($filepath, json_encode($data));
      return true;
    }

    public function getAccountData($id, $acc = null) {
      if (!$acc)
        $acc = $this->getAccount($id);

      $localStorage = $this->getAccountFile($acc, "localStorage.json");
      $creds = $this->getAccountFile($acc, "auth.json");
      $html = $this->getAccountFile($acc, "main.html");
      $cookies = $this->getAccountFile($acc, "cookies.json");
      $ua = $this->getAccountFile($acc, "ua.txt");
      $csrftoken = $this->getAccountFile($acc, "csrf.token");
      return [$localStorage, $html, $cookies, $ua, $csrftoken, $creds];
    }

    public function saveAccount($id, $auth = null, $tokens = null) {
      $acc = $this->getAccount($id);
      if ($tokens) {
        $this->saveAccountFile($acc, "data", $tokens);
      }

      if ($auth) {
        $this->saveAccountFile($acc, "auth", $auth);
      }

      return true;
    }

    public function randAccount() {
      $accs = $this->listAccount();
      $accsProxies = $this->assocArray($this->proxies, $accs);

      $id = array_rand($accs);
      $accdata = $this->getAccountData($id, $accs[$id]);
      /*
      $this->doLog("Account: ".$id);
      $this->doLog("Acc: ".json_encode($accs[$id]));
      $this->doLog("Accdata: ".json_encode($accdata));
      $this->doLog("Proxy: ".$accsProxies[$id]);
      */
      return [$id, $accs[$id], $accdata, $accsProxies[$id]];
    }

    public function aMember($method, $path, $post = null) {
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      if ($method == "GET") {
        curl_setopt($ch, CURLOPT_URL, $this->aMember_url.$path."?".http_build_query($post));
      } else if ($post) {
        curl_setopt($ch, CURLOPT_URL, $this->aMember_url.$path);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: application/x-www-form-urlencoded"));
      }

      $result = curl_exec($ch);

      curl_close($ch);
      if ($this->isJson($result)) {
        return json_decode($result);
      } else {
        return $result;
      }
    }

    /**
     * @param string $targetURL
     * @return false|resource
     */
    private function _cleanLeak($str, $what, $with) {
     $str = str_replace($what, $with, $str);
     $str = str_replace(urlencode($what), urlencode($with), $str);
     $str = str_replace(base64_encode($what), base64_encode($with), $str);
     $str = str_replace(urlencode(base64_encode($what)), urlencode(base64_encode($with)), $str);
     return $str;
    }

    private function cleanLeak($str, $acc, $reverse = false) {
      $ua = (isset($acc[2][3]) ? $acc[2][3] : "Mozilla/5.0(Windows; U; Windows NT 7.0; rv:1.9.2) Gecko/20100101 Firefox/3.6");

     if ($reverse) {
       $str = $this->_cleanLeak($str, $acc[2][5]->username, $this->fakeEmail);
       $str = $this->_cleanLeak($str, "app.".$this->TARGET_URL, $_SERVER['HTTP_HOST']);
       $str = $this->_cleanLeak($str, $ua, $_SERVER['HTTP_USER_AGENT']);
     } else {
       $str = $this->_cleanLeak($str, $this->fakeEmail, $acc[2][5]->username);
       $str = $this->_cleanLeak($str, $_SERVER['HTTP_HOST'], "app.".$this->TARGET_URL);
       $str = $this->_cleanLeak($str, $_SERVER['HTTP_USER_AGENT'], $ua);
     }

     return $str;
    }


    private function fixChar($char) {
      //return mb_convert_encoding($char, 'HTML-ENTITIES', 'UTF-8');
      //return urlencode(utf8_encode($char));
      //return $char;
      if (!$char || $char == "")
        return $char;
      return $char;
      //return htmlspecialchars($char);
      //return htmlentities($char);
      //return iconv(mb_detect_encoding($char, mb_detect_order(), true), "UTF-8", $char);
    }

    private function fixCharJSON($json) {
      if (!$json)
        return $json;
      $isArr = is_array($json);
      foreach($json as $dcid => $dcval) {
        if (is_object($dcval)) {
          if ($isArr) {
            $json[intval($dcid)] = static::fixCharJSON($dcval);
          } else {
            $json->{$dcid} = static::fixCharJSON($dcval);
          }
        } elseif (is_array($dcval)) {
          if ($isArr) {
            $json[intval($dcid)] = static::fixCharJSON($dcval);
          } else {
            $json->{$dcid} = static::fixCharJSON($dcval);
          }
        } else {
          if ($isArr) {
            $json[intval($dcid)] = static::fixChar($dcval);
          } else {
            $json->{$dcid} = static::fixChar($dcval);
          }
        }
      }
      return $json;
    }

    protected function createRequest($cookiesManager, $account, $targetURL, $newpost = null)
    {
        /*
        $targetURL = str_replace("%22BACKLINKINPUT%22", urlencode(base64_decode(' ')), $targetURL);
        */
        $request = curl_init();
        /*
        if (strstr($targetURL, 'seBacklinks')) {
          echo $targetURL;
          exit(1);
        }
        */

        if (strstr($targetURL, "matomo")) {
          return 200;
        }


        $debug = $this->isDebug();
        $postdt = "";
        // Set input data
        $requestMethod = $newpost ? "POST" : strtoupper($this->ri($_SERVER['REQUEST_METHOD']));
        if ($debug)$this->doLog("[".$requestMethod."] $targetURL");
        $POSTIS = !empty($_POST) ? $_POST : [];
        if ($requestMethod === "PUT" || $requestMethod === "PATCH") {
            curl_setopt($request, CURLOPT_POSTFIELDS, file_get_contents('php://input'));
        } elseif ($requestMethod === "POST") {
            $data = $newpost ? $newpost : array();

            if (!empty($_FILES)) {
                if (!$this->hasCURLFileSupport()) {
                    curl_setopt($request, CURLOPT_SAFE_UPLOAD, false);
                }

                foreach ($_FILES as $fileName => $file) {
                    $filePath = realpath($file['tmp_name']);

                    if ($this->hasCURLFileSupport()) {
                        $data[$fileName] = new CURLFile($filePath, $file['type'], $file['name']);
                    } else {
                        $data[$fileName] = '@' . $filePath;
                    }
                }
            }

            $aPostParams = null;
            /*
            if (empty($POSTIS)) {
              $aPostParams = json_decode($this->cleanInput(file_get_contents('php://input')), true);
            }
            */

            //$postdt = http_build_query(array_merge($data, $aPostParams ? $aPostParams : $POSTIS));
            //$postdt = str_replace($_SERVER['HTTP_HOST'], "app.".$this->TARGET_URL, $postdt);
        }

        $oldheaders = $this->getIncomingRequestHeaders($this->getSkippedHeaders());
        $isjson = false;
        $needsbearer = false;
        $referer = null;
        $origin = null;
        $needscookie = false;
        $needsdatadome = false;
        $hascsrf = false;
        $hasinput = false;
        $hastype = false;

        foreach($oldheaders as $id=>$header) {

          if (strstr(strtolower($header), "cookie:")) {
            $needscookie = true;
          } else if (strstr(strtolower($header), "client-referer")) {
            $headers[] = str_replace($this->THIS_DOMAIN, 'app.'.$this->TARGET_URL, $header);
            if (strstr($header, '/#/login')) {
              touch($this->PATHACCS.$account[1]."/auth.required");
            }
          } else if (strstr(strtolower($header), "referer:") || strstr(strtolower($header), "origin:")) {
            if (!strstr($targetURL, ".js") && !strstr($targetURL, ".css") && strstr(strtolower($header), "referer:"))
              $headers[] = str_replace($this->THIS_DOMAIN, 'app.'.$this->TARGET_URL, $header);
            $referer = trim(str_replace("referer:","",str_replace("Referer:","",$header)));
            $refererFix = explode("/",$referer);
            unset($refererFix[0]);
            unset($refererFix[1]);
            unset($refererFix[2]);
            $refererFix = join("/",$refererFix);
            $referer = "https://app.".$this->TARGET_URL."/".$refererFix;

            $origin = "https://app.".$this->TARGET_URL;

          } else if (strstr(strtolower($header), "x-csrf-token:")) {
            $hascsrf = true;
            $headers[] = $header;

          } else if (strstr(strtolower($header), "content-type:")) {
            //$header = str_replace("; charset=utf-8","", $header);
            $hastype = $header;
            //$headers[] = $header;
            if (strstr(strtolower($header), "application/json")) {
              $isjson = true;
            }

          } else if (strstr(strtolower($header), "cf-connecting-ip")) {
            $splh = explode(": ", $header);
            $headers[] = $splh[0].": ".explode(":", $account[3])[0];

          } else if (strstr(strtolower($header), "x-input")) {
            $splh = explode(": ", $header);
            $hasinput = $splh[1];
          } else if (
            !strstr(strtolower($header), "host:")
            &&
            !strstr(strtolower($header), "cf-ipcountry")
            &&
            !strstr(strtolower($header), "x-forwarded")
            &&
            !strstr(strtolower($header), "access-control-allow")
            &&
            !strstr(strtolower($header), "user-agent")
            &&
            !strstr(strtolower($header), "sec-")
            &&
            !strstr(strtolower($header), "dnt")
            &&
            !strstr(strtolower($header), "chrome")
            &&
            !strstr(strtolower($header), "content-security")
            //&&
            //!strstr(strtolower($header), "cache-control")
            &&
            !strstr(strtolower($header), "pragma")
            &&
            !strstr(strtolower($header), "accept-encoding")
            &&
            !strstr(strtolower($header), "content-length")
            &&
            !strstr(strtolower($header), "connection")
          ) {
            $headers[] = $header;
          }
        }
        $nUrl = str_replace("https://", "http://", $targetURL).($hasinput ? (strstr($targetURL,"?") ? "&" : "?")."input=".$hasinput : '');
        curl_setopt($request, CURLOPT_URL, $nUrl);
        $headers[] = 'User-Agent: '.(isset($account[2][3]) ? $account[2][3] : "Mozilla/5.0(Windows; U; Windows NT 7.0; rv:1.9.2) Gecko/20100101 Firefox/3.6");

        $cookiedata = $cookiesManager->get();
        $datadomecookie = false;
        if (isset($account[2][2])) {
          foreach($account[2][2] as $cook) {
            if (($needsbearer || strstr($targetURL,"/api/")) && $cook->name == 'auth_token') {
              $headers[] = 'Authorization: Bearer '.$cook->value;
            }
          }
        }



        $filteredCookies = [];
        foreach($cookiesManager->getObj('ahrefs') as $id => $vals) {
          if (!$vals)
            continue;
//          $this->doLog("Cookie ".$id." checking ".$targetURL." vs ".(isset($vals->domain) ? $vals->domain : ''));
          if (isset($vals->domain)) {
            $domaincheck = ltrim($vals->domain, '.');
//            if (strstr($targetURL, $domaincheck)) {
//              $this->doLog("Adding "."$id=".$vals->value);
//              $filteredCookies[] = "$id=".rawurlencode($vals->value);
                if (!strstr($id, "intercom"))
                  $filteredCookies[] = "$id=".$vals->value;
//            }
          }
        }

        //$headers[] = "Accept-Language: en-US,en;q=0.5";
        $headers[] = "Sec-Fetch-Dest: document";
        $headers[] = "Sec-Fetch-Mode: navigate";
        $headers[] = "Sec-Fetch-Site: none";
        $headers[] = "Sec-Fetch-User: ?1";
        //  $cookiedata .= '; auth_token=' . $account[2][1].";";
        if (!$this->byGet)
          $headers[] = 'Cookie: ' . $this->cleanLeak(join("; ", $filteredCookies), $account);
        //if ($isjson)$headers[] = 'Content-Type: application/json;charset=UTF-8';
        //if (isset($account[2]) && isset($account[2][0]) && isset($account[2][0]->data))
        //  $headers[] = 'Authorization: Bearer '.$account[2][0]->data->token;
        //$headers[] = 'Accept-Encoding: deflate, gzip, br';
        $headers[] = 'Connection: keep-alive';

        if (($requestMethod === "POST" || $requestMethod === "PUT") && empty($_FILES)) {

          $postdt = $this->cleanInput(file_get_contents('php://input'));
          /*
          if (static::isJson($postdt)) {
            //$dc = static::fixCharJSON(json_decode($postdt));
            //$postdt = json_encode($dc);
          } elseif (strstr($hastype, "urlencoded") && strstr($postdt, "=") && strstr($postdt, "&")) {
            $values = array();

            $nv_strings = explode ('&', $payload);
            foreach ($nv_strings as $s) {
              $nv = explode ('=', $s, 2);
              $namex = urldecode ($nv[0]);
              $valuex = (isset ($nv[1]) ? urldecode ($nv[1]) : null);
              $values[$namex] = mb_convert_encoding($valuex, 'HTML-ENTITIES', 'UTF-8');
            }
            $postdt = http_build_query($values);
          } else {
            //$postdt = mb_convert_encoding($postdt, 'HTML-ENTITIES', 'UTF-8');
          }
          */


          //$this->doLog("\n\n\n\n\nPOsT-------------->".$postdt."\n\n\n\n\n");
          /*
            $headers[] = 'Content-Type: application/json;charset=UTF-8';
            curl_setopt($request, CURLOPT_POSTFIELDS, $dtpost);

          if (count($aPostParams ? $aPostParams : $POSTIS) > 0) {
            $postdt = json_encode((array) $aPostParams ? $aPostParams : $POSTIS);
          }
          */
        }
        $bypassprox = false;
        if ($postdt && $postdt != "") {
          //if (strstr($postdt, "keyword")) {
            //$bypassprox = true;
          //} else {
            $postdt = $this->cleanLeak($postdt, $account);
          //}
          //$headers[] = 'Content-Length: ' . strlen($postdt);
          //if (!$hascsrf)
          //  $headers[] = 'X-CSRF-Token: ' . $account[2][4];

          if (strstr($postdt, '"limit":')) {
            $postdtjson = json_decode($postdt);
            if (isset($postdtjson) && isset($postdtjson->seed) && isset($postdtjson->seed->Keywords)) {
              $ddid = join(",",$postdtjson->seed->Keywords);
              $postdtjson->limit = $this->csvLimit;
              $postdtjson->offset = $postdtjson->limit * (($_SESSION[$ddid] && $_SESSION[$ddid]['c']) ? $_SESSION[$ddid]['c'] : 0);
              $postdt = json_encode($postdtjson);

              if ($_SESSION[$ddid]) {

                $_SESSION[$ddid]['c']++;
                if ($_SESSION[$ddid]['c'] > $this->csvLimitTotal) {
                  if((time() - $_SESSION[$ddid]['date']) > 86400) {
                    $_SESSION[$ddid] = (array)[
                      "c" => 1,
                      "date" => time()
                    ];
                  } else {
                    echo "    <meta http-equiv=\"refresh\" content=\"0;URL='https://ah01.cheapseospytools.com/limit-over.php'\" />     Limit over, contact admin";
                    exit(1);
                  }
                }

              } else {
                $_SESSION[$ddid] = (array)[
                  "c" => 1,
                  "date" => time()
                ];
              }
            }
          }
        }

        $newHeaders = Array();
        foreach($headers as $headr) {
          if (strstr($postdt, '"{\"input\":{') && strstr(strtolower($headr), 'content-type: ')) {
            if (!strstr(strtolower($headr), 'application/json')) {
              $newHeaders[] = 'Content-Type: application/json';
            } else {
              $newHeaders[] = $this->cleanLeak($headr, $account);
            }
          } else {
            $newHeaders[] = $this->cleanLeak($headr, $account);
          }
        }
        $headers = $newHeaders;



        curl_setopt($request, CURLOPT_CONNECTTIMEOUT, 0);
        curl_setopt($request, CURLOPT_TIMEOUT, 400); //timeout in seconds

        if (strtolower($requestMethod) === "post" || strtolower($requestMethod) === "put") {
          curl_setopt($request, CURLOPT_POSTFIELDS, $postdt);
        }
        if ($postdt && strstr($postdt, '"{\"input\":{')) {
          //$postdt = ltrim($postdt, '"');
          //$postdt = rtrim($postdt, '"');
          //$postdt = str_replace('\\', '\\\\', $postdt);
          //$postdt = str_replace('"', '\\"', $postdt);
          $postdt = str_replace('\\"', '\\\\"', $postdt);
          //$postdt = "encoded_bin--->".base64_encode("\"{\\\"input\\\":{\\\"targets\\\":[{\\\"target\\\":\\\"cnn.com/\\\"},{\\\"target\\\":\\\"foxnews.com/\\\"}],\\\"filter\\\":{\\\"volumeMode\\\":\\\"monthly\\\"}},\\\"signatureInfo\\\":{\\\"notAfter\\\":\\\"2024-08-08T23:34:41Z\\\",\\\"signature\\\":\\\"9+d8/vKjYBGHw9d6BtylnTVwP1RLuPNJY0ESANUeE7I=\\\"}}\"");
          //$postdt = str_replace("\\", "\\\\", $postdt);
          //$postdt = str_replace("\\", "\\\\", $postdt);
          $postdt = "encoded_bin--->".base64_encode($postdt);

          //$postdt = str_replace('\\"', '\\\"', $postdt);
          /*          /*
          if ($isjson) {
            //$postdt = json_decode($postdt);
            //$postdt = http_build_query($postdt);
            echo $postdt;
            exit(1);
            $headers[] = 'Content-Type: application/x-www-form-urlencoded';
            $headers[] = 'Content-Length: '.strlen($postdt);
          } else {
            if ($hastype)
              $headers[] = $hastype;
            else
              $headers[] = 'Content-Type: application/json';
          }
          if ($hastype)
          $headers[] = $hastype;
          else
          */
          $headers[] = 'Content-Type: application/json; charset=utf-8';

          /*


          */
          //$headers[] = "Content-Length: ".strlen($postdt);

          //echo "\n\n\n\n\n-------------->".join("\n", $headers)."\n\n\n\n\n".$targetURL;
          //echo "\n\n\n".$postdt."\n\n\n";
          //exit(1);

        } else {
          if ($hastype)
            $headers[] = $hastype;
        }
        $this->doLog("\n\n\n\n\n-------------->".join("\n", $headers)."\n\n\n\n\n".$targetURL);
        if ($account) {
          if (!$bypassprox)
            $headers[] = 'x-proxy: '.$account[3];
          if ($postdt && $postdt != "") {
            curl_setopt_array($request, [
                CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
                CURLOPT_TCP_KEEPALIVE => 3,
                CURLOPT_TCP_KEEPIDLE => 30,
                CURLOPT_TCP_KEEPINTVL => 15,
                CURLOPT_FOLLOWLOCATION => false,
                CURLOPT_SSL_VERIFYHOST => false,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_PROXY => $bypassprox ? $account[3] : $this->cfbypassProxy,
                CURLOPT_HEADER => $this->CURLOPT_HEADER,
                CURLOPT_RETURNTRANSFER => $this->CURLOPT_RETURNTRANSFER,
                CURLINFO_HEADER_OUT => true,
                CURLOPT_HTTPHEADER => $headers
            ]);
          } else {
            curl_setopt_array($request, [
                CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
              CURLOPT_FOLLOWLOCATION => false,
                CURLOPT_SSL_VERIFYHOST => false,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_PROXY => $bypassprox ? $account[3] : $this->cfbypassProxy,
                CURLOPT_HEADER => $this->CURLOPT_HEADER,
                CURLOPT_RETURNTRANSFER => $this->CURLOPT_RETURNTRANSFER,
                CURLINFO_HEADER_OUT => true,
                CURLOPT_HTTPHEADER => $headers
            ]);
          }
        } else {
          curl_setopt_array($request, [
              CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
              CURLOPT_FOLLOWLOCATION => false,
              CURLOPT_SSL_VERIFYHOST => false,
              CURLOPT_SSL_VERIFYPEER => false,
              CURLOPT_PROXY => $bypassprox ? $account[3] : $this->cfbypassProxy,
              CURLOPT_HEADER => $this->CURLOPT_HEADER,
              CURLOPT_RETURNTRANSFER => $this->CURLOPT_RETURNTRANSFER,
              CURLINFO_HEADER_OUT => true,
              CURLOPT_HTTPHEADER => $headers
          ]);

        }

        return $request;
    }

    public function doLog($msg) {
      //file_put_contents($this->PATH."debug.log", $msg."\n", FILE_APPEND);
    }
    public function doLog2($msg) {
      //file_put_contents($this->PATH."debug2.log", $msg."\n", FILE_APPEND);
    }



    public function cleanResponse($account, $url, $body) {

      //$body = str_replace("intercom", "localhost", $body);
      if (strstr($url, "googletagmanager")) {
        if (strstr($url, "gtm.js")) {
        }
        $body = "";


      } elseif (
        strstr($url, ".js") && (!strstr($url, "/data/"))
      ) {


        /*
        if (strstr($url, "site-explorer")) {
          $body = str_replace(',shape:I.filterMap', ',shape:I.slice(0,1).filterMap', $body);

        }
        if (strstr($body, ',params:')) {
        $body = preg_replace('/\,params\:([\w]+)\,/', ',params:window.cMc($1),', $body);
        $body .="function cMc(inx) {console.log('CMC',inx); return {hd:{},t1:{}};};";
      }
        */
        $body = str_replace("accounts.google.com", "localhost", $body);
        $body = preg_replace('/([\w\-]+)\.'.str_replace('.', '\.', $this->TARGET_URL).'/i', $this->THIS_DOMAIN.'/_$1', $body);
        $body = str_replace($this->TARGET_URL, $this->THIS_DOMAIN, $body);
        foreach ($this->blacklistUrls as $Burl) {
          $body = preg_replace_callback(
              "'".$Burl."([^\"\'\s]+)'",
              function($matches) {
                  return "localhost";
              },
              $body);
        }
      } elseif (
        strstr($url, ".css")
      ) {


        $body = preg_replace('/([\w\-]+)\.'.str_replace('.', '\.', $this->TARGET_URL).'/i', $this->THIS_DOMAIN.'/_$1', $body);
        $body = str_replace($this->TARGET_URL, $this->THIS_DOMAIN, $body);


        foreach ($this->blacklistUrls as $Burl) {
          $body = preg_replace_callback(
              "'".$Burl."([^\"\'\s]+)'",
              function($matches) {
                  return "localhost";
              },
              $body);
        }
        $body = preg_replace_callback(
            "'([\"\'\(]{1})?(http:|https:|ws:)?\/\/([^\"\'\s\)]+)'",
            function($matches) {
              if (strstr($matches[3], $this->THIS_DOMAIN) || strstr($matches[3], 'localhost'))
                return $matches[0];
              else {
                $urlf = ($matches[2] && $matches[2] != "" ? $matches[2] : "https:")."//".$matches[3];
                if (filter_var($urlf, FILTER_VALIDATE_URL)) {
                  return $matches[1]. "//".$this->THIS_DOMAIN."/?q=".urlencode(base64_encode($urlf));
                } else {
                  return $matches[0];
                }
              }
            },
            $body);

      } elseif (
        ((strstr($body, "<title") && strstr($body, "<body")) || ((strstr($body, "<style") || strstr($body, "<title")) && strstr($body, "<script")))
      ) {


        //$body = str_replace("static-app.".$this->TARGET_URL, $this->THIS_DOMAIN."/_static-app", $body);
        //$body = str_replace("app.".$this->TARGET_URL, $this->THIS_DOMAIN, $body);
        $body = preg_replace('/([\w\-]+)\.'.str_replace('.', '\.', $this->TARGET_URL).'/i', $this->THIS_DOMAIN.'/_$1', $body);
        $body = str_replace($this->TARGET_URL, $this->THIS_DOMAIN, $body);

        $sub = explode("/",$_SERVER['REQUEST_URI'])[1];

				$proxyguard = "const bPass = ['".join("','",$this->blacklistUrls)."'];
        const _0x9551=['open','prototype','://','apply','https://','indexOf','http://','http://localhost','https://www.','call','http://localhost/','http://www.','/index.php?q=','###SERVERNAME###'];(function(_0x58007f,_0x95517a){const _0x405cec=function(_0x1b4461){while(--_0x1b4461){_0x58007f['push'](_0x58007f['shift']());}};_0x405cec(++_0x95517a);}(_0x9551,0xa6));const _0x405c=function(_0x58007f,_0x95517a){_0x58007f=_0x58007f-0x0;let _0x405cec=_0x9551[_0x58007f];return _0x405cec;};const _0x1b3341=_0x405c,phpJSGuard_url=_0x1b3341('0x1'),reFetcher=window['fetch'];window['fetch']=function(){const _0x5c8bc5=_0x1b3341;let _0x1b4461=arguments,_0x576297=arguments[0x0];if(_0x576297[_0x5c8bc5('0x7')](_0x5c8bc5('0x6')+phpJSGuard_url)===0x0||_0x576297[_0x5c8bc5('0x7')](_0x5c8bc5('0xa')+phpJSGuard_url)===0x0||_0x576297[_0x5c8bc5('0x7')]('http://'+phpJSGuard_url)===0x0||_0x576297[_0x5c8bc5('0x7')](_0x5c8bc5('0xd')+phpJSGuard_url)===0x0||_0x576297[_0x5c8bc5('0x7')]('/')===0x0)return reFetcher['apply'](this,arguments);const _0x20172b=bPass['filter'](_0x4e6967=>{const _0x146783=_0x5c8bc5;return _0x576297[_0x146783('0x7')](_0x4e6967)===0x0||_0x4e6967[_0x146783('0x7')]('://')===-0x1&&_0x576297[_0x146783('0x7')](_0x4e6967)!==-0x1;});if(_0x20172b&&_0x20172b[0x0])return _0x1b4461[0x0]=_0x5c8bc5('0x6')+phpJSGuard_url+_0x5c8bc5('0x0')+encodeURIComponent(_0x576297),reFetcher[_0x5c8bc5('0x5')](this,_0x1b4461);return _0x1b4461[0x0]=_0x5c8bc5('0xc'),reFetcher['apply'](this,_0x1b4461);},!function(_0x289022){const _0x43630b=_0x1b3341;XMLHttpRequest['prototype'][_0x43630b('0x2')]=function(_0x6c3324,_0x31753a,_0x127f5f,_0x6f4f95,_0x311035){const _0x39b84f=_0x43630b;if(_0x31753a[_0x39b84f('0x7')](_0x39b84f('0x6')+phpJSGuard_url)===0x0||_0x31753a['indexOf'](_0x39b84f('0xa')+phpJSGuard_url)===0x0||_0x31753a[_0x39b84f('0x7')](_0x39b84f('0x8')+phpJSGuard_url)===0x0||_0x31753a['indexOf'](_0x39b84f('0xd')+phpJSGuard_url)===0x0||_0x31753a[_0x39b84f('0x7')]('/')===0x0)return _0x289022[_0x39b84f('0xb')](this,_0x6c3324,_0x31753a,_0x127f5f,_0x6f4f95,_0x311035);const _0x2a9270=bPass['filter'](_0x1d5731=>{const _0x2eef3f=_0x39b84f;return _0x31753a[_0x2eef3f('0x7')](_0x1d5731)===0x0||_0x1d5731[_0x2eef3f('0x7')](_0x2eef3f('0x4'))===-0x1&&_0x31753a[_0x2eef3f('0x7')](_0x1d5731)!==-0x1;});if(_0x2a9270&&_0x2a9270[0x0])return _0x289022[_0x39b84f('0xb')](this,_0x6c3324,'https://'+phpJSGuard_url+'/index.php?q='+encodeURIComponent(_0x31753a),_0x127f5f,_0x6f4f95,_0x311035);_0x289022[_0x39b84f('0xb')](this,_0x6c3324,_0x39b84f('0x9'),_0x127f5f,_0x6f4f95,_0x311035);};}(XMLHttpRequest[_0x1b3341('0x3')][_0x1b3341('0x2')]);";
				$proxyguard = str_replace("###SERVERNAME###", $_SERVER['SERVER_NAME'],$proxyguard);
        $windowsetls = "function b64nic(str) {percentEncodedStr = atob(str).split('').map(function(c) {return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);}).join('');return decodeURIComponent(percentEncodedStr);};
";
        if ($account[2][0]) {
          foreach($account[2][0] as $lsk => $lsv) {
            $windowsetls .= "window.localStorage.setItem('".str_replace("'","\\'",$lsk)."', b64nic('".base64_encode(($lsv && $lsv != "null" && $lsv != "undefined") ? $lsv : '')."'));";
          }
        }

        $part1 = explode('<script nonce="', $body)[0];
        $part2 = explode('</script>' , explode('<script nonce="', $body)[1]);
        $part2[0] = "";
        $part2 = join("", $part2);
        $body = $part1.$part2;


        $body = preg_replace('/\<script defer([^\>]+)/i', "<meta/", $body);

        $body = str_replace('</title>', "</title><script>
        function sAnc() {
          var anchors = document.getElementsByTagName('a');
          for (var i = 0; i < anchors.length; i++) {
            anchors[i].href = anchors[i].href.replace(/app\.ahrefs\.com/, '".$this->THIS_DOMAIN."');
            anchors[i].href = anchors[i].href.replace(/([\-\w]+)\.ahrefs\.com/, '".$this->THIS_DOMAIN."/_$1');
            anchors[i].href = anchors[i].href.replace(/ahrefs\.com/, '".$this->THIS_DOMAIN."');
          }
        }
        setInterval(sAnc, 300);
        const {fetch: origFetch} = window;
        window.fetch = (...args) => {
          if (args[0].indexOf('google.') !== -1 || args[0].indexOf('googletagmanager') !== -1)
            return {};
          if (args[0].indexOf('?input=') !== -1 || args[0].indexOf('&input=') !== -1) {
            let nbd = JSON.parse(decodeURIComponent(args[0].split('input=')[1].split('&')[0]));
            args[0] = args[0].replace(/[\?\&]input\=[^&]+&?/, '##S##');
            const trysp = args[0].split('##S##');
            if (trysp[1].trim() != ''){
              args[0] = trysp[0]+'?'+trysp[1];
            } else {
              args[0] = trysp[0];
            }
            args[1].headers.push(['x-input', encodeURIComponent(JSON.stringify(nbd))]);

            //args[1].headers.push(['accept-encoding', 'br');
            //args[1].headers = args[1].headers.filter(h => h[0] != 'accept-encoding' && h[0] != 'Accept-Encoding')
          }
          return origFetch(...args);
        };</script>


        <script>
function removeDivAndReload() {
  // Get the parent element with class 'css-12var3r-header navbar'
  var parentDiv = document.querySelector('.css-12var3r-header.navbar');

  // Check if the parent element exists
  if (parentDiv) {
    // Get the child div to remove
    var divToRemove = parentDiv.querySelector('.css-1rwqq8c.css-0.css-1mq5fur-row.css-zcxndt');

    // Check if the child div to remove exists
    if (divToRemove) {
      // Remove the child div from the DOM
      divToRemove.remove();
    }
  }
}

// Call removeDivAndReload initially
removeDivAndReload();

// Reload the script every second
setInterval(removeDivAndReload, 1000);



        </script>







       









        <script>".$windowsetls."</script><style>#TK__NotifyContainer{display:none} #userMenuDropdown {display:none !important;}, .helpMenu{display:none !important;}  div[data-state='closed'].css-1rwqq8c.css-0.css-1mq5fur-row.css-zcxndt {display: none;}
</style>", $body);
        $body = str_replace('window.intercomSettings = {', 'window.intercomSettings = {};window.xintercomSettings = {', $body);

        //$body = preg_replace('/window\.intercomSettings \= \{([^}]+)/i', "window.intercomSettings = {", $body);

        //<script type='text/javascript' src='/jquery.min.js'></script>



        $body = preg_replace_callback(
            "'([\"\'\(]{1})?(http:|https:|ws:)?\/\/([^\"\'\s\)]+)'",
            function($matches) {
              if (strstr($matches[3], $this->THIS_DOMAIN) || strstr($matches[3], 'localhost'))
                return $matches[0];
              else {
                $urlf = ($matches[2] && $matches[2] != "" ? $matches[2] : "https:")."//".$matches[3];
                if (filter_var($urlf, FILTER_VALIDATE_URL)) {
                  return $matches[1]. "//".$this->THIS_DOMAIN."/?q=".urlencode(base64_encode($urlf));
                } else {
                  return $matches[0];
                }
              }
            },
            $body);

        foreach ($this->blacklistUrls as $Burl) {
          $body = preg_replace_callback(
              "'".$Burl."([^\"\'\s]+)'",
              function($matches) {
                  return "localhost";
              },
              $body);
        }


      } else {
        //try use cache
      }

      $body = $this->cleanLeak($body, $account, true);
      return $body;
    }

    public function isJson($string) {
      try {
       json_decode($string);
       return (json_last_error() == JSON_ERROR_NONE);
      } catch (exception $e) {
       return false;
      }
    }

    public function allowCors() {
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: *");
        //header("Content-Type: application/json");

        // Allow from any origin
        if (isset($_SERVER['HTTP_ORIGIN'])) {
            header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
            header('Access-Control-Allow-Credentials: true');
            header('Access-Control-Max-Age: 86400');    // cache for 1 day
        }

      // Access-Control headers are received during OPTIONS requests
      if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

          if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
              // may also be using PUT, PATCH, HEAD etc
              header("Access-Control-Allow-Methods: GET, POST, OPTIONS");

          if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
              header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

          exit(0);
      }

      header('Access-Control-Allow-Headers:Origin, Accept, Accept-  Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, X-Response-Time, X-PINGOTHER, X-CSRF-Token,Authorization');
      header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS');
      header('Access-Control-Allow-Origin: *');
    }


    public function assocArray($arr1, $arr2) {
      $k = 0;
      $arr= Array();
      foreach($arr2 as $kk => $obj) {
        $arr[$kk] = $arr1[$k];
        if ($k == (count($arr1) - 1)) {
          $k = 0;
        } else $k++;
      }
      return $arr;
    }

    public function cleanInput($str) {
      return trim(str_replace(array("\r", "\n"), '', $str));
    }

    public function allowIP($user_id) {
      $members = file_exists($this->PATH."members.json") ? json_decode(file_get_contents($this->PATH."members.json")) : (object) array();
      if ($members->{$user_id}) {
        $allowed = file_exists($this->PATH."allowed.json") ? json_decode(file_get_contents($this->PATH."allowed.json")) : (object) array();
        $allowed->{$user_id} = $_SERVER['REMOTE_ADDR'];
        file_put_contents($this->PATH."allowed.json", json_encode($allowed));
        return true;
      }
      return false;
    }

    public function allowedIP() {
      $allowed = file_exists($this->PATH."allowed.json") ? json_decode(file_get_contents($this->PATH."allowed.json")) : (object) array();
      $allowed_vals = array_values((array) $allowed);
      if (in_array($_SERVER['REMOTE_ADDR'],$allowed_vals))
        return (isset($_SESSION['authh10']) && $_SESSION['authh10'] && $_SESSION['authh10'] != "");
      return false;
    }



    private function get_between($string,$start,$end)
    {
        $string = " ".$string;
        $ini = strpos($string, $start);
        if($ini==0) return "";
        $ini += strlen($start);
        $len = strpos($string, $end, $ini) - $ini;

        return substr($string, $ini, $len);
    }

    private function getMime($txt) {
      $mime_types = array(

            'txt' => 'text/plain',
            'htm' => 'text/html',
            'html' => 'text/html',
            'php' => 'text/html',
            'css' => 'text/css',
            'js' => 'application/javascript',
            'json' => 'application/json',
            'xml' => 'application/xml',
            'swf' => 'application/x-shockwave-flash',
            'flv' => 'video/x-flv',

            // images
            'png' => 'image/png',
            'jpe' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'jpg' => 'image/jpeg',
            'gif' => 'image/gif',
            'bmp' => 'image/bmp',
            'ico' => 'image/vnd.microsoft.icon',
            'tiff' => 'image/tiff',
            'tif' => 'image/tiff',
            'svg' => 'image/svg+xml',
            'svgz' => 'image/svg+xml',

            // archives
            'zip' => 'application/zip',
            'rar' => 'application/x-rar-compressed',
            'exe' => 'application/x-msdownload',
            'msi' => 'application/x-msdownload',
            'cab' => 'application/vnd.ms-cab-compressed',

            // audio/video
            'mp3' => 'audio/mpeg',
            'qt' => 'video/quicktime',
            'mov' => 'video/quicktime',

            // adobe
            'pdf' => 'application/pdf',
            'psd' => 'image/vnd.adobe.photoshop',
            'ai' => 'application/postscript',
            'eps' => 'application/postscript',
            'ps' => 'application/postscript',

            // ms office
            'doc' => 'application/msword',
            'rtf' => 'application/rtf',
            'xls' => 'application/vnd.ms-excel',
            'ppt' => 'application/vnd.ms-powerpoint',

            // open office
            'odt' => 'application/vnd.oasis.opendocument.text',
            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',

            // fonts
            'ttf' => 'font/ttf',
            'woff' => 'font/woff',
            'woff2' => 'font/woff2',
        );
        if ($mime_types[$txt]) {
          return $mime_types[$txt];
        } else {
          return false;
        }
    }

    private function parseCookies($file) {
        $string = file_get_contents($file);
        $cookies = array();

        $lines = explode("\n", $string);

        // iterate over lines
        foreach ($lines as $line) {

            // we only care for valid cookie def lines
            if (isset($line[0]) && substr_count($line, "\t") == 6) {

                // get tokens in an array
                $tokens = explode("\t", $line);

                // trim the tokens
                $tokens = array_map('trim', $tokens);

                $cookie = array();

                // Extract the data
                $cookie['domain'] = $tokens[0];
                $cookie['flag'] = $tokens[1];
                $cookie['path'] = $tokens[2];
                $cookie['secure'] = $tokens[3];

                // Convert date to a readable format
                $cookie['expiration'] = date('Y-m-d h:i:s', $tokens[4]);

                $cookie['name'] = $tokens[5];
                $cookie['value'] = $tokens[6];

                // Record the cookie.
                $cookies[] = $cookie;
            }
        }

        return $cookies;
    }

    private function addCookie($path, $name, $value = null, $exp = 0, $domain = null, $bTail = null, $pathx = null, $bSecure = null) {
        $cont = file_get_contents($path."/cookies.txt");
        $cr = (strpos($cont, "\r\n") !== false) ? "\r\n" : "\n";
        $lineObj = array(
            '',      // domain
            'FALSE', // tailmatch
            '/',     // path
            'FALSE', // secure
            '',
            '',
            ''
        );

        if (!is_null($domain))
            $lineObj[0] = $domain;
        if (!is_null($bTail))
            $lineObj[1] = $bTail ? 'TRUE' : 'FALSE';
        if (!is_null($pathx))
            $lineObj[2] = $pathx;
        if (!is_null($bSecure))
            $lineObj[3] = $bSecure ? 'TRUE' : 'FALSE';
        if (!is_null($exp))
            $lineObj[4] = $exp;
        if (!is_null($name))
            $lineObj[5] = $name;
        if (!is_null($value))
            $lineObj[6] = $value;

        file_put_contents($path."/cookies.txt", implode("\t", $lineObj) . $cr, FILE_APPEND);
    }

    public function limitRequest($method, $post = null) {
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      if ($method == "GET") {
        curl_setopt($ch, CURLOPT_URL, "https://limit.cheapseospytools.com/api.php?".http_build_query($post));
      } else if ($post) {
        curl_setopt($ch, CURLOPT_URL, "https://limit.cheapseospytools.com/api.php");
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: application/x-www-form-urlencoded"));
      }

      $result = curl_exec($ch);

      curl_close($ch);
      return $result;
    }

    public function limitCharges() {
      if (!isset($_COOKIE['amember_ru']))
        return 0;
      $amember_username = $_COOKIE['amember_ru'];
      if ($amember_username == "")
        return 0;

      $charges = $this->limitRequest("GET", (array)[
        "amember" => $amember_username
      ]);
      if (!is_numeric($charges))
        return 0;
      return intval($charges);
    }

    public function limitAllowed() {
      if (!isset($_COOKIE['amember_ru']))
        return false;
      $amember_username = $_COOKIE['amember_ru'];
      if ($amember_username == "")
        return false;

      $allowed = $this->limitRequest("POST", (array)[
        "amember" => $amember_username,
        "domain" => $_SERVER['SERVER_NAME'],
        "path" => $_SERVER['REQUEST_URI']
      ]);

      if (!strstr($allowed, "[OK]"))
        return false;
      return true;
    }

    public function cacheControl($file) {
      $file_last_mod_time = filemtime(__FILE__);
      $content_last_mod_time = filemtime($file);
      $etag = '"' . $file_last_mod_time . '.' . $content_last_mod_time . '"';

      header('Cache-Control: max-age=86400');
      header('ETag: ' . $etag);

      header_remove( 'Pragma' );
      header_remove( 'Expires' );

      if(isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
        if($_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
          header('HTTP/1.1 304 Not Modified', true, 304);
          exit();
        }
      }
    }

    /**
     * @return int HTTP response code (200, 404, 500, etc.)
     */
    public function run()
    {
      try {
        $debug = $this->isDebug();

        if (!$this->isAuthenticated()) {
            throw new RuntimeException($this->HEADER_HTTP_PROXY_AUTH . ' header is invalid');
        }

        $account = $this->randAccount();
        if (!$account || !isset($account[2][3]) || $account[2][3] == "") {
          echo "Please try again later...";
          return 200;
        }
        if (isset($_GET) && isset($_GET['q'])) {
          $targetURL = base64_decode(urldecode(explode("?q=",$_SERVER['REQUEST_URI'])[1]));
          $this->byGet = true;
          unset($_GET['q']);
          unset($_REQUEST['q']);

          if (!strstr($targetURL, $this->TARGET_URL) && strstr($targetURL,".amazon.")) {
            header("Location: ".$targetURL);
            return 301;
          }
        } else {
          $targetURL = static::getTargetUrl();
        }




        $targetURLFinalLast = $targetURL;
        if (
          strstr($targetURLFinalLast, "/cdn-cgi/rum")
          || strstr($targetURLFinalLast, "/tkTrackEvent")
          || strstr($targetURLFinalLast, "/tkChromeReport")
          || strstr($targetURLFinalLast, "matomo")
        ) {

          return 200;
        }

        $actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        $extension = pathinfo(parse_url(explode("#",explode("?",$targetURLFinalLast)[0])[0], PHP_URL_PATH), PATHINFO_EXTENSION);

        if (
          //strtoupper($_SERVER['REQUEST_METHOD']) == "GET"
          //&&
          (
            // Keyword domain/subdomain search
            (
              (strstr($targetURL, "/v2-site-explorer/")
              ||
              strstr($targetURL, "/site-explorer/"))
              &&
              strstr($targetURL, "target=")
            )

            // API/Ajax methods
            //|| (strstr($targetURL, "/keywords-explorer/") && strstr($targetURL, "keyword="))
            || ((strstr($targetURL, "/ke") || strstr($targetURL, "/se")) && strstr($targetURL, "?input"))
            || (strstr($targetURL, "/v4/keIdeas"))
            || (strstr($targetURL, "/v4/keTrafficByDomains"))
            || (strstr($targetURL, "/v4/keTrafficByPages"))
            || (strstr($targetURL, "/v4/keListOverviewKwGroups"))
            || (strstr($targetURL, "/v2-batch-analysis"))
            || (strstr($targetURL, "/content-explorer"))
          )
        ) {
          if (
            !isset($_SESSION['lastcharge'])
            ||
            (time() - $_SESSION['lastcharge']) > 10
          ) {
            $_SESSION['lastcharge'] = time();
            if (!$this->limitAllowed()) {
              echo "    <meta http-equiv=\"refresh\" content=\"0;URL='https://ah01.cheapseospytools.com/limit-over.php'\" />     Limit over, contact admin";
              return 200;
            }
          }
        } else {
          $charges = $this->limitCharges();
          if ($charges <= 0) {
            echo "    <meta http-equiv=\"refresh\" content=\"0;URL='https://ah01.cheapseospytools.com/limit-over.php'\" />     Limit over, contact admin";
            return 200;
          }
        }

        // Check for blacklisted paths
        foreach ($this->blacklistPaths as $Burl) {
          if (strstr($targetURLFinalLast, $Burl)) {
             echo "<script>window.location.href='https://ah01.cheapseospytools.com/site-explorer';</script>";
            return 200;
          }
        }


        if (
          /*
          (
            !strstr($targetURLFinalLast, "chunk-BEZMEFSE")
            &&
            !strstr($targetURLFinalLast, "chunk-VUTA")
            &&
            !strstr($targetURLFinalLast, "lag-icon.min-")

          )
          &&
          */
          (strstr($targetURLFinalLast, "/api/v1/customers/segment-track")
          ||
          strstr($targetURLFinalLast, "/notification/main/check-unread-count")
          ||
          in_array($extension, $this->cacheFiles))
        ) {
          $cache = $this->hasCache($targetURLFinalLast);
          if ($cache) {
            $this->doLog($targetURLFinalLast." Has cache ".$extension);
            if ($extension && $extension != "") {
              $extmime = $this->getMime($extension);
              if ($extmime) {
                header('Content-Type: '.$extmime.';charset=UTF-8');
              }
            }
            echo $cache;
            return 200;
          }
        } else {
          if (!strstr($targetURLFinalLast, "/socket.io/"))
            $this->doLog("Not caching ".$targetURLFinalLast."\nFrom:".$actual_link."\nExt: ".$extension);
        }
        /*

        if (strstr($targetURLFinalLast, "matomo.php")) {
          echo "";
          return 200;
        }
        */

        if (strstr($targetURLFinalLast, "/socket.io/")) {
          echo "";
          return 404;
        }




        if (!file_exists($this->PATHACCS.$account[1].'/cookies.file'))
          touch($this->PATHACCS.$account[1].'/cookies.file');
        $cookiesManager = new CookiesManager($this->PATHACCS.$account[1].'/cookies.file');
      $this->doLog(json_encode($cookiesManager->getObj('ahrefs')));
        /*
        if ($account[2][1] && strstr($account[2][1], "<html") && ((count(explode("/",$targetURLFinalLast))-1) <= 3 || strstr($targetURLFinalLast, '?accountId='))) {

          $setCookies = $cookiesManager->getObj();
          if ($setCookies && !empty($setCookies)) {
            foreach($setCookies as $setc => $sobj) {
              if (!isset($sobj['domain']) || strstr($sobj['domain'], "helium10"))
                 setcookie($setc, $sobj['value'], time() + (60*15), $sobj['path']);
            }
          }

          //$this->doLog("Log: ".$account[2][1]);
          //echo $this->cleanResponse($account, $targetURLFinalLast, $account[2][1]);
          //return 200;
        }
        */

        $this->allowCors();
        //$targetURLFinalLast = "https://dev01.seovpn.net/capture.php";
        $targetURLFinalLast = $this->cleanLeak($targetURLFinalLast, $account);



        if (strstr($targetURLFinalLast, '/user/login')) {
          echo "Please try again later.";
          touch($this->PATHACCS.$account[1]."/auth.required");
          return 200;
        }
        $request = $this->createRequest($cookiesManager, $account, $targetURLFinalLast);
        $attempts = 0;
        $response = curl_exec($request);

        $headerSize = curl_getinfo($request, CURLINFO_HEADER_SIZE);
        $responseHeader = substr($response, 0, $headerSize);
        $responseBody = substr($response, $headerSize);
        $responseInfo = curl_getinfo($request);


        /*
        $this->doLog("RESPONSE HDEADER: ".$responseHeader);
        $this->doLog("RESPONSE BODY: ".$responseBody);
        $this->doLog("json: ".json_encode($responseInfo));
        */
        $responseCode = $responseInfo['http_code'];
        $redirectCount = $this->ri($responseInfo['redirect_count'], 0);
        $requestHeaders = preg_split('/[\r\n]+/', $this->ri($responseInfo['request_header'], ''));

        if ($responseCode === 0) {
          curl_close($request);
          do {
            //static::doLog($targetURLFinalLast." Failed proxy, retrying... ".$attempts);
            sleep(rand(1, 3));
            //file_put_contents($this->PATH."debug.log", "Trying ".$attempts." ".$targetURLFinalLast."\n", FILE_APPEND);
            $response = curl_exec($request);
            //file_put_contents($this->PATH."debug.log", $response."\n", FILE_APPEND);
            $attempts++;
            $headerSize = curl_getinfo($request, CURLINFO_HEADER_SIZE);
            $responseHeader = substr($response, 0, $headerSize);
            $responseBody = substr($response, $headerSize);
            $responseInfo = curl_getinfo($request);



            $responseCode = $responseInfo['http_code'];
            $redirectCount = $this->ri($responseInfo['redirect_count'], 0);
            $requestHeaders = preg_split('/[\r\n]+/', $this->ri($responseInfo['request_header'], ''));


          } while(($responseCode === 0 || ($responseCode === 200 && empty($responseBody))) && $attempts <= 3);
          //file_put_contents($this->PATH."debug.log", "Trying2 ".$attempts." ".$targetURLFinalLast." ".$responseCode." ".$responseBody."\n", FILE_APPEND);
          if (($responseCode === 0 || ($responseCode === 200 && empty($responseBody)))) {
            $responseCode = 200;
          }
        }

        $finalRequestURL = curl_getinfo($request, CURLINFO_EFFECTIVE_URL);
        if ($redirectCount > 0 && !empty($finalRequestURL)) {
            $finalRequestURLParts = parse_url($finalRequestURL);
            $effectiveURL = $this->ri($finalRequestURLParts['scheme'], 'http') . '://' .
                $this->ri($finalRequestURLParts['host']) . $this->ri($finalRequestURLParts['path'], '');
        }


        $cookieslist = [];

        //----------------------------------
        //define('COOKIE_DOMAIN', $this->TARGET_ROOTURL);
        // Split header text into an array.
        $responseHeaders = $this->splitResponseHeaders($responseHeader);
        // Pass headers to output
        $contntt = "";
        foreach ($responseHeaders as $header) {
            $header = $this->cleanLeak($header, $account, true);
            $headerParts = preg_split('/:\s+/', $header, 2);
            if (count($headerParts) !== 2) {
                throw new RuntimeException("Can not parse header \"$header\"");
            }

            $headerName = $headerParts[0];
            $loweredHeaderName = strtolower($headerName);

            $headerValue = $headerParts[1];
            $loweredHeaderValue = strtolower($headerValue);

            // Pass following headers to response
            if (in_array($loweredHeaderName,
                ['content-type', 'content-language', 'server'])) {
                $headerValue = str_replace("app.".$this->TARGET_URL, $this->THIS_DOMAIN, $headerValue);
                $headerValue = str_replace("www.".$this->TARGET_URL, $this->THIS_DOMAIN, $headerValue);
                $headerValue = str_replace("*.".$this->TARGET_URL, $this->THIS_DOMAIN, $headerValue);
                if ($loweredHeaderName == 'content-type') {
                  $contntt = $headerValue;
                  //echo "$headerName: $headerValue \n";
                  //exit(1);
                  header("$headerName: $headerValue");
                } else {

                  header("$headerName: $headerValue");
                }
            } // Replace cookie domain and path
            elseif ($loweredHeaderName === 'x-set-cookie') {
              if (strstr($headerValue, "\n")) {
                foreach(split("\n", $headerValue) as $c) {
                  $cookieslist[] = $c;
                }
              } else {
                $cookieslist[] = $headerValue;
              }


              $newValue = preg_replace('/((?>domain)\s*=\s*)[^;\s]+/', '\1.' . $_SERVER['HTTP_HOST'], $headerValue);
              $newValue = preg_replace('/\s*;?\s*path\s*=\s*[^;\s]+/', '', $newValue);
              header("$headerName: $newValue", false);
            } elseif (strpos($loweredHeaderName, 'x-') === 0) {
                header("$headerName: $headerValue");
            } elseif (strpos($loweredHeaderName, 'location') === 0) {
              $fixsite = $headerValue;
              $fixsite = str_replace("app.".$this->TARGET_URL, $this->THIS_DOMAIN, $fixsite);
              $fixsite = preg_replace('/([\w\-]+)\.?'.str_replace('.', '\.', $this->TARGET_URL).'/i', $this->THIS_DOMAIN.'/$1', $fixsite);

              if (!strstr($fixsite, $this->TARGET_URL))
                header("Location: ".$fixsite);
              else
                header("Location: ".$this->THIS_URL);
            } // Replace cookie domain and path
            elseif ($loweredHeaderName === 'set-cookie') {
              if (!$this->byGet) {
                if (strstr($headerValue, "\n")) {
                  foreach(split("\n", $headerValue) as $c) {
                    $cookieslist[] = $c;
                  }
                } else {
                  $cookieslist[] = $headerValue;
                }
              }
              $newValue = preg_replace('/((?>domain)\s*=\s*)[^;\s]+/', '\1.' . $_SERVER['HTTP_HOST'], $headerValue);
              $newValue = preg_replace('/\s*;?\s*path\s*=\s*[^;\s]+/', '', $newValue);
              //header("$headerName: $newValue", false);
            } elseif ($loweredHeaderName === 'content-encoding') {
              /*
              echo "\nResponse:\n".gzdecode($responseBody)."\n";
              echo "\n".$loweredHeaderValue."\n";
              exit(1);
              */
                //$responseBody = gzdecode($responseBody);
            } else {

              if (
                strtolower($headerName) == 'cache-control'
                ||
                strtolower($headerName) == 'etag'
                ||
                strtolower($headerName) == 'pragma'
                ||
                strtolower($headerName) == 'expires'
                ||
                strstr(strtolower($headerName), "content-security")
              ) {

              } else {
                header("$headerName: $headerValue");
              }

            }
        }



        if ($cookieslist && count($cookieslist)) {
          //$cookiesManager->update($cookieslist);
          $recooks = [];
          foreach($cookiesManager->getObj('ahrefs') as $id => $vals) {
            $vals->name = $id;
            if (isset($vals->expires))
              $vals->expires = strtotime($vals->expires);

            if (isset($vals->{'max-age'}))
              unset($vals->{'max-age'});

            array_push($recooks, $vals);
          }
          //file_put_contents($this->PATHACCS.$account[1]."/cookies.json", json_encode($recooks));
        }


        if (!$this->byGet && $responseBody && strstr($responseBody, "<html")) {
          /*
          $setCookies = $cookiesManager->getObj();
          if ($setCookies && !empty($setCookies)) {
            foreach($setCookies as $setc => $sobj) {
              if (!isset($sobj['domain']) || strstr($sobj['domain'], "helium10"))
                 setcookie($setc, $sobj['value'], time() + (60*15), $sobj['path']);
            }
          }
          */
          if (strstr($responseBody, '<meta name="csrf-token"')) {
            $csrftoken = explode('<meta name="csrf-token" content="', $responseBody)[1];
            $csrftoken = explode('">', $csrftoken)[0];
            file_put_contents($this->PATHACCS.$account[1]."/csrf.token", $csrftoken);
          }

          //$this->doLog("Log: ".$account[2][1]);
          //echo $this->cleanResponse($account, $targetURLFinalLast, $account[2][1]);
          //return 200;
        }

        $responseBody = $this->cleanResponse($account, $finalRequestURL, $responseBody);
        http_response_code($responseCode);

        //----------------------------------
        $debug = true;
        if ($debug) {
            $this->doLog('Headers sent to proxy' . PHP_EOL . PHP_EOL);
            $this->doLog(implode(PHP_EOL, $this->getIncomingRequestHeaders($this->getSkippedHeaders())));
            $this->doLog($this->HR);

            if (!empty($_GET)) {
                $this->doLog('$_GET sent to proxy' . PHP_EOL . PHP_EOL);
                $this->doLog(json_encode($_GET));
                $this->doLog($this->HR);
            }

            if (!empty($_POST)) {
                $this->doLog('$_POST sent to proxy' . PHP_EOL . PHP_EOL);
                $this->doLog(json_encode($_POST));
                $this->doLog($this->HR);
            }

            if (!empty($_REQUEST)) {
                $this->doLog('$_REQUEST sent to proxy' . PHP_EOL . PHP_EOL);
                $this->doLog(json_encode($_REQUEST));
                $this->doLog($this->HR);
            }

            $testinp = file_get_contents('php://input');
            if (!empty($testinp)) {
                $this->doLog('$INPUT sent to proxy' . PHP_EOL . PHP_EOL);
                $this->doLog($testinp);
                $this->doLog($this->HR);
            }

            $this->doLog('Headers sent to target' . PHP_EOL . PHP_EOL);
            $this->doLog(implode(PHP_EOL, $requestHeaders));
            $this->doLog($this->HR);

            if (isset($effectiveURL) && $effectiveURL !== $targetURL) {
                $this->doLog("Request was redirected from \"$targetURL\" to \"$effectiveURL\"");
                $this->doLog($this->HR);
            }

            $this->doLog('Headers received from target' . PHP_EOL . PHP_EOL);
            $this->doLog($responseHeader);
            $this->doLog($this->HR);

            $this->doLog('Headers sent from proxy to client' . PHP_EOL . PHP_EOL);
            $this->doLog(implode(PHP_EOL, headers_list()));
            $this->doLog($this->HR);

            $this->doLog('Body sent from proxy to client' . PHP_EOL . PHP_EOL);
            $this->doLog("\nBody:".$responseBody."\n");
        }

        if (strstr($responseBody, '["Error","Forbidden"]')) {
          echo "Please try again later.";
          touch($this->PATHACCS.$account[1]."/auth.required");
          return 200;
        }


        /*
        if (strstr($contntt, 'text/csv')) {
          $lessl = explode("\n", $responseBody);
          if (count($lessl) > 2000)
            $lessl = array_slice($lessl, -2000);
          $lessl = join("\n", $lessl);


          if (
            !isset($_SESSION['csvDown'])
            ||
            (time() - $_SESSION['lastcharge']) > 10
          ) {
            $_SESSION['lastcharge'] = time();
            if (!$this->limitAllowed()) {
              echo "    <meta http-equiv=\"refresh\" content=\"0;URL='https://ah01.cheapseospytools.com/limit-over.php'\" />     Limit over, contact admin";
              return 200;
            }
          }

          return 200;
        }
        */

        /*
    		if (strpos($targetURLFinalLast, 'https://api.junglescout.com') === 0 && strstr($responseBody, "'geo.captcha-delivery.com'}</script><script src=\"https://ct.captcha-delivery.com")){
          touch($this->PATHACCS.$account[1]."/auth.required");
          echo "Please try again later";
          return 200;
        }
        */

        echo $responseBody;
        if (
          strstr($targetURLFinalLast, "/api/v1/customers/segment-track")
          ||
          strstr($targetURLFinalLast, "/notification/main/check-unread-count")
          ||
          in_array($extension, $this->cacheFiles)
        )
          $this->saveCache($targetURLFinalLast, $responseBody);
        if($debug)$this->doLog($targetURLFinalLast." Exiting with response code: ".$responseCode);
        return $responseCode;
      } catch (exception $e) {
        if($debug)$this->doLog($targetURLFinalLast." Error message: ".$e->getMessage());
        return 500;
      }
    }
}
$proxy = new Proxy();
if (!$proxy->isInstalledWithComposer()) {
    $proxy->checkCompatibility();
    $proxy->registerErrorHandlers();
    $responseCode = $proxy->run();

    if ($proxy->isResponseCodeOk($responseCode)) {
      exit(0);
    } else {
      exit($responseCode);
    }
}
