<?php

class yandex_verify
{
  public $email;
  public $verifier_email;
  public $port;
  private $mx;
  private $connect;
  private $errors;
  private $debug;
  private $debug_raw;

  private $_passport_signup_page_url = 'https://passport.yandex.com/registration';
  private $_passport_signup_ajax_url = 'https://passport.yandex.com/registration';
  private $_passport_username_check_url = 'https://passport.yandex.com/registration-validations/login';
  private $page_content;
  private $page_headers;

  public function __construct($email = null, $port = 25)
  {
    $this->debug = array();
    $this->debug_raw = array();
    if (!is_null($email)) {
      $this->debug[] = 'Initialized with Email: ' . $email . ', Port: ' . $port;
      $this->set_email($email);
    } else {
      $this->debug[] = 'Initialized with no email';
    }
    $this->set_port($port);
  }

  public function set_email($email)
  {
    $this->email = $email;
    $this->debug[] = 'Email was set to ' . $email;
  }

  public function get_email()
  {
    return $this->email;
  }

  public function set_port($port)
  {
    $this->port = $port;
    $this->debug[] = 'Port was set to ' . $port;
  }

  public function get_port()
  {
    return $this->port;
  }

  public function get_errors()
  {
    return array('errors' => $this->errors);
  }

  public function get_debug($raw = false)
  {
    if ($raw) {
      return $this->debug_raw;
    } else {
      return $this->debug;
    }
  }

  public function verify()
  {
    $this->debug[] = 'Verify function was called.';

    $is_valid = false;
    $is_valid = $this->check_username();
    return $is_valid;
  }

  private function get_domain($email)
  {
    $email_arr = explode('@', $email);
    $domain = array_slice($email_arr, -1);
    return $domain[0];
  }
  private function find_mx()
  {
    $domain = $this->get_domain($this->email);
    $mx_ip = false;
    // Trim [ and ] from beginning and end of domain string, respectively
    $domain = ltrim($domain, '[');
    $domain = rtrim($domain, ']');

    if ('IPv6:' == substr($domain, 0, strlen('IPv6:'))) {
      $domain = substr($domain, strlen('IPv6') + 1);
    }

    $mxhosts = array();
    if (filter_var($domain, FILTER_VALIDATE_IP)) {
      $mx_ip = $domain;
    } else {
      getmxrr($domain, $mxhosts, $mxweight);
    }

    if (!empty($mxhosts)) {
      $mx_ip = $mxhosts[array_search(min($mxweight), $mxweight)];
    } else {
      if (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
        $record_a = dns_get_record($domain, DNS_A);
      } elseif (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
        $record_a = dns_get_record($domain, DNS_AAAA);
      }

      if (!empty($record_a)) {
        $mx_ip = $record_a[0]['ip'];
      }

    }

    $this->mx = $mx_ip;
  }


  private function connect_mx()
  {
    //connect
    $this->connect = @fsockopen($this->mx, $this->port);
  }

  private function add_error($code, $msg)
  {
    $this->errors[] = array('code' => $code, 'message' => $msg);
  }

  private function clear_errors()
  {
    $this->errors = array();
  }

  private function check_username()
  {
    $this->debug[] = 'Validating a passport email address...';
    $this->debug[] = 'Getting the sign up page content...';
    $this->fetch_page();

    $cookies = $this->get_cookies();
    $fields = $this->get_fields();

    $this->debug[] = 'Adding the email to fields...';
    $fields['login'] = $this->email;

    $this->debug[] = 'Ready to submit the POST request to validate the email.';

    $response = $this->request_validation('passport', $cookies, $fields);

    $this->debug[] = 'Parsing the response...';
    $response_errors = json_decode($response, true);
    $this->debug[] = 'Searching errors for exisiting username error...';
    if (isset($response_errors['status']) && $response_errors['status'] == 'ok') {
      $this->debug[] = 'Username is avilable';
      return true;
    } else if (isset($response_errors[0]) && $response_errors[0] == 'login.not_available') {
      $this->debug[] = 'This username is not available';
      return false;
    }
  }



  private function fetch_page($cookies = '')
  {
    if ($cookies) {
      $opts = array(
        'http' => array(
          'method' => "GET",
          'header' => "Accept-language: en\r\n" .
            "Cookie: " . $cookies . "\r\n"
        )
      );
      $context = stream_context_create($opts);
    }
    if ($cookies) {
      $this->page_content = file_get_contents($this->_passport_signup_page_url, false, $context);
    } else {
      $this->page_content = file_get_contents($this->_passport_signup_page_url);
    }

    if ($this->page_content === false) {
      $this->debug[] = 'Could not read the sign up page.';
      $this->add_error('200', 'Cannot not load the sign up page.');
    } else {
      $this->debug[] = 'Sign up page content stored.';
      $this->debug[] = 'Getting headers...';
      $this->page_headers = $http_response_header;
      $this->debug[] = 'Sign up page headers stored.';
    }
  }

  private function get_cookies()
  {
    $this->debug[] = 'Attempting to get the cookies from the sign up page...';
    if ($this->page_content !== false) {
      $this->debug[] = 'Extracting cookies from headers...';
      $cookies = array();
      // Input value found
      foreach ($this->page_headers as $hdr) {
        if (preg_match('/^Set-Cookie:\s*(.*?;).*?$/i', $hdr, $matches)) {
          $cookies[] = $matches[1];
        }
      }
      if (count($cookies) > 0) {
        $this->debug[] = 'Cookies found: ' . implode(' ', $cookies);
        return $cookies;
      } else {
        $this->debug[] = 'Could not find any cookies.';
      }
    }
    return false;
  }

  private function get_fields()
  {
    $dom = new DOMDocument();
    $fields = array();
    if (@$dom->loadHTML($this->page_content)) {
      $this->debug[] = 'Parsing the page for input fields...';
      $xp = new DOMXpath($dom);
      $nodes = $xp->query('//input');
      foreach ($nodes as $node) {
        if (in_array($node->getAttribute('name'), array('track_id', 'login')))
          $fields[$node->getAttribute('name')] = $node->getAttribute('value');
      }

      $js = $xp->query('//body/script[@type="text/javascript"]')->item(0)->nodeValue;
      $start = strpos($js, '{');
      $end = strrpos($js, '}}');
      $json = substr($js, $start);
      $data = json_decode($json, true);

      $fields['csrf_token'] = $data['common']["csrf"];

      $this->debug[] = 'Extracted fields.';
    } else {
      $this->debug[] = 'Something is worng with the page HTML.';
      $this->add_error('210', 'Could not load the dom HTML.');
    }
    return $fields;
  }

  private function request_validation($service, $cookies, $fields)
  {
    if ($service == 'passport') {
      $headers = array();
      $headers[] = 'Origin: https://passport.yandex.com';
      $headers[] = 'Host: passport.yandex.com';
      $headers[] = 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36';
      $headers[] = 'Content-type: application/x-www-form-urlencoded charset=UTF-8';
      $headers[] = 'Accept: application/json, text/javascript, */*; q=0.01';
      $headers[] = 'Referer: https://passport.yandex.com/';
      $headers[] = 'Accept-Encoding: gzip, deflate, br';
      $headers[] = 'Accept-Language: en-US,en;q=0.9';
      $headers[] = 'X-Requested-With: XMLHttpRequest';
      $headers[] = 'Sec-Fetch-Dest: empty';
      $headers[] = 'Sec-Fetch-Mode: cors';
      $headers[] = 'Sec-Fetch-Site: same-origin';
      $headers[] = 'Sec-GPC: 1';

      $cookies_str = implode(' ', $cookies);
      $headers[] = 'Cookie: ' . $cookies_str;
      $url = $this->_passport_username_check_url;

      $post = '';
      foreach ($fields as $key => $value) {
        $post .= $key . "=" . $value . "&";
      }



      $ch = curl_init($url);

      curl_setopt($ch, CURLOPT_URL, $url);

      curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

      $result = curl_exec($ch);

    }
    return $result;
  }



}
