<?php
class pub_outlook_verify
{
    public $email;
    public $verifier_email;
    public $port;
    private $errors = [];
    private $debug = [];
    private $debug_raw = [];
    private $page_content;
    private $page_headers;

    private $_hotmail_signin_page_url = 'https://login.live.com/';
    private $_hotmail_username_check_url = 'https://login.live.com/GetCredentialType.srf?wa=wsignin1.0';
    private $_hotmail_domains = ['hotmail.com', 'live.com', 'outlook.com', 'msn.com'];

    public function __construct($email = null, $verifier_email = null, $port = 25)
    {
        if ($email && $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 ['errors' => $this->errors];
    }

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

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

    private function getEmailAccFromEmail($email)
    {
        return explode('@', $email)[0];
    }

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

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

    private function validate_hotmail()
    {
        $this->debug[] = 'Validating a hotmail email address...';
        $this->fetch_page();

        $cookies = $this->get_cookies();
        $this->fetch_page(implode(' ', $cookies));
        $cookies = $this->get_cookies();

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

        $json_response = json_decode($response, true);

        if (isset($json_response['IfExistsResult']) || isset($json_response['ErrorHR'])) {
            if (
                (isset($json_response['IfExistsResult']) && $json_response['IfExistsResult'] == 0) ||
                (isset($json_response['ErrorHR']) && $json_response['ErrorHR'] == '800478CE')
            ) {
                $this->debug[] = 'This Email Address Exist';
                return true;
            } else {
                $this->debug[] = 'This Email Address Not Found';
            }
        } else {
            $this->debug[] = 'IfExistsResult or ErrorHR index not set in the response';
        }
        return false;
    }

    private function fetch_page($cookies = '')
    {
        $opts = $cookies ? [
            'http' => [
                'method' => "GET",
                'header' => "Accept-language: en\r\nCookie: $cookies\r\n"
            ]
        ] : [];

        $context = $cookies ? stream_context_create($opts) : null;
        $this->page_content = file_get_contents($this->_hotmail_signin_page_url, false, $context);

        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->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) {
            $cookies = [];
            foreach ($this->page_headers as $hdr) {
                if (preg_match('/^Set-Cookie:\s*(.*?;).*?$/i', $hdr, $matches)) {
                    $cookies[] = $matches[1];
                }
            }
            if ($cookies) {
                $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 = [];
        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 wrong with the page HTML.';
            $this->add_error('210', 'Could not load the dom HTML.');
        }
        return $fields;
    }

    private function request_validation($cookies, $fields)
    {
        $headers = [
            'Origin: https://login.live.com',
            'hpgid: 33',
            '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',
            'Content-type: application/json; charset=UTF-8',
            'Accept: application/json',
            'Referer: https://login.live.com',
            'Accept-Encoding: gzip, deflate, br',
            'Accept-Language: en-US,en;q=0.8,ar;q=0.6',
            'Cookie: ' . implode(' ', $cookies)
        ];

        $ch = curl_init($this->_hotmail_username_check_url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
        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);

        $result = curl_exec($ch);
        if (curl_errno($ch)) {
            $this->debug[] = 'Curl error: ' . curl_error($ch);
        }

        return $result;
    }

    private function prep_hotmail_fields($cookies)
    {
        $fields = [];
        if (preg_match('/<input type="hidden" (.*?) value="(.*?)"/', $this->page_content, $matches)) {
            $fields['flowToken'] = $matches[2];
        } else {
            $this->debug[] = 'flowtoken not found';
        }

        foreach ($cookies as $cookie) {
            list($key, $val) = explode('=', $cookie, 2);
            if ($key == 'uaid') {
                $fields['uaid'] = $val;
                break;
            }
        }

        $fields['username'] = strtolower($this->email);
        return $fields;
    }
}