<?php
class outlook365_verify
{

  public $email;
  public $verifier_email;
  private $errors;
  private $debug;
  private $debug_raw;
  public $port;

  private $_hotmail_signin_page_url = 'https://login.microsoftonline.com/';
  private $_hotmail_username_check_url = 'https://login.microsoftonline.com/common/GetCredentialType?mkt=en-US';
  private $_hotmail_domains = array('hotmail.com', 'live.com', 'outlook.com', 'msn.com');
  private $page_content;
  private $page_headers;

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

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

  public function get_verifier_email()
  {
    return $this->verifier_email;
  }


  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->validate_hotmail();
    return $is_valid;
  }

  private function getEmailAccFromEmail($email)
  {
    $email_address = explode('@', $email);

    $domain = array_shift($email_address);

    return $domain;
  }


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

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

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

    $cookies = $this->get_cookies();
    if (!is_array($cookies)) {
      $this->debug[] = 'Failed to retrieve cookies, aborting validation.';
      return false;
    }

    $this->debug[] = 'Sending another request to get the needed cookies for validation...';
    $this->fetch_page('hotmail', implode(' ', $cookies));
    $cookies = $this->get_cookies();
    if (!is_array($cookies)) {
      $this->debug[] = 'Failed to retrieve secondary cookies, aborting validation.';
      return false;
    }

    $this->debug[] = 'Preparing fields...';
    $fields = $this->prep_hotmail_fields($cookies);

    // var_dump($fields);


    $this->debug[] = 'Ready to submit the POST request to validate the email.';
    $response = $this->request_validation($cookies, $fields);

    $this->debug[] = 'Searching username error...';
    $json_response = json_decode($response, true);
    //	  var_dump($json_response['IfExistsResult']);
//	  	  var_dump($json_response);

    if ($json_response['IfExistsResult'] == 0) {
      $this->debug[] = 'This Email Address Exist';
      return true;
    } else {
      $this->debug[] = 'This Email Address Not Found';
    }
    return false;
  }

  private function fetch_page($type, $cookies = '')
  {
    $url = $this->_hotmail_signin_page_url;
    $ch = curl_init();
    $headers = array(
      "Accept-language: en",
      "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    );
    if ($cookies) {
      $headers[] = "Cookie: " . $cookies;
    }

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 30 seconds timeout
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    // Capture headers to emulate $http_response_header
    $responseHeaders = array();
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) use (&$responseHeaders) {
      $len = strlen($header);
      $header = trim($header);
      if (!empty($header)) {
        $responseHeaders[] = $header;
      }
      return $len;
    });

    $this->page_content = curl_exec($ch);

    if (curl_errno($ch)) {
      $this->debug[] = 'cURL Error: ' . curl_error($ch);
      $this->page_content = false;
    }


    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 = $responseHeaders;
      $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) {
        $fields[$node->getAttribute('name')] = $node->getAttribute('value');
      }

      $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($cookies, $fields)
  {

    $submit_email = $this->email;

    $headers = array();
    $headers[] = 'Origin: https://login.microsoftonline.com';
    $headers[] = 'hpgid: 33';
    $headers[] = 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36';
    $headers[] = 'Content-type: application/json; charset=UTF-8';
    $headers[] = 'Accept: application/json';
    $headers[] = 'Referer: https://login.microsoftonline.com';
    $headers[] = 'Accept-Encoding: gzip, deflate, br';
    $headers[] = 'Accept-Language: en-US,en;q=0.8,ar;q=0.6';

    $cookies_str = implode(' ', $cookies);
    $headers[] = 'Cookie: ' . $cookies_str;


    $url = $this->_hotmail_username_check_url;

    // set post fields
    $post = json_encode($fields);

    //	var_dump($post);

    $ch = curl_init($url);

    curl_setopt($ch, CURLOPT_URL, $url);

    //	curl_setopt($ch, CURLOPT_ENCODING, "");
    curl_setopt($ch, CURLOPT_HEADER, 0);

    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

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

    $result = curl_exec($ch);


    //		var_dump($result);



    return $result;
  }


  private function prep_hotmail_fields($cookies)
  {
    $fields = array();
    $result = preg_match('/<input type="hidden" (.*?) value="(.*?)"/', $this->page_content, $matches);
    $flowToken = null;
    if (!$result) {
      // Could not find input	
      $this->debug[] = 'flowtoken not found';
    } else {
      //print_r($matches);	
      //$cookies[]=''	
      $flowToken = $matches[2];
    } //exit;	
    foreach ($cookies as $cookie) {
      list($key, $val) = explode('=', $cookie, 2);
      if ($key == 'uaid') {
        $fields['uaid'] = $val;
        break;
      }
    }
    $fields['flowToken'] = $flowToken;
    $fields['username'] = strtolower($this->email);
    return $fields;
  }

}