Войдите в учетную запись Google через Curl - PullRequest
0 голосов
/ 28 мая 2018

Я пытаюсь заставить этот скрипт работать: https://github.com/aaronpk/Google-Voice-PHP-API

Google недавно изменил способ входа в вашу учетную запись.Каковы были бы шаги для входа через cURL в Google?

Он выдаст это сейчас при попытке опубликовать в форму на этой странице (https://accounts.google.com/signin/challenge/sl/password):

Type: Exception

Message: Could not parse for GALX or gxf token. Inputs from page: array ()

1 Ответ

0 голосов
/ 28 мая 2018

без особой проверки этого кода, вот код, который я использую для входа в gmail, используя hhb_curl (и заметьте: изначально я притворялся iPhone, потому что было проще войти через страницу мобильного входачем страница входа на рабочий стол, но в итоге я перенес ее на версию для настольного компьютера, но в коде все еще есть остатки мобильной версии. Кроме того, иногда gmail произвольно запрашивает у вас подтверждение вашей электронной почты для восстановления при использовании этого метода, таким образом, $Переменная recoveryEmailChallengeAnswer. Это происходит не каждый раз, но Google замечает, что при входе в систему что-то «выключено», и, таким образом, запрашивает подтверждение восстановления электронной почты случайным образом. Мой код прозрачно обрабатывает эту ситуацию.):

function loginGmail(string $username, string $password, string $recoveryEmailChallengeAnswer, bool $requestHtmlVersion = true): \hhb_curl {
    $hc = new hhb_curl ( '', true );
    $hc->setopt_array ( array (
            CURLOPT_TIMEOUT => 20, // i just have a shitty connection :(
            CURLOPT_CONNECTTIMEOUT => 10 
    ) );
    if (0) {
        $hc->setopt_array ( array (
                CURLOPT_USERAGENT => 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1' 
        ) );
    }
    $html = $hc->exec ( 'https://gmail.com' )->getStdOut ();
    $domd = @DOMDocument::loadHTML ( $html );
    $inputs = getDOMDocumentFormInputs ( $domd, true, false ) ['gaia_loginform'];
    // hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ) & die();
    $loginUrl = $domd->getElementById ( "gaia_loginform" )->getAttribute ( "action" );
    $inputs ['Email'] = $username;
    $html = $hc->setopt_array ( array (
            CURLOPT_POST => 1,
            CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
            CURLOPT_URL => $loginUrl 
    ) )->exec ()->getStdOut ();
    $domd = @DOMDocument::loadHTML ( $html );
    $inputs = getDOMDocumentFormInputs ( $domd, true, false ) ['gaia_loginform'];
    // hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs );
    $loginUrl = $domd->getElementById ( "gaia_loginform" )->getAttribute ( "action" );
    $inputs ['Passwd'] = $password;
    try {
        $starttime = microtime ( true );
        $html = $hc->setopt_array ( array (
                CURLOPT_POST => 1,
                CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
                CURLOPT_URL => $loginUrl 
        ) )->exec ()->getStdOut ();
    } finally{
        // hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs, (microtime ( true ) - $starttime) ) & die ();
    }
    $domd = @DOMDocument::loadHTML ( $html );
    $xp = new DOMXPath ( $domd );
    $loginErrors = $xp->query ( '//span[contains(@class,"error-msg")]' );
    $loginErrorText = '';
    foreach ( $loginErrors as $tmp ) {
        $tmp = trim ( $tmp->textContent );
        if (strlen ( $tmp )) {
            $loginErrorText .= ' - ' . $tmp;
        }
    }
    $authChallenge = $domd->getElementById ( "challengePickerList" );
    if (NULL !== $authChallenge) {
        // gotdammit... got an auth challenge page, asking you to choose a challenge
        $loginErrorText .= ' - got an auth challenge page, asking you to choose a challenge: ' . trim ( $authChallenge->textContent );
        // TODO: automatically select "provide recovery email" here instead of throwing a login error exception.
    } else {
        if (false !== stripos ( $html, 'Enter recovery email' ) && NULL !== ($authChallenge = $domd->getElementById ( "challenge" ))) {
            // got an auth challenge for providing recovery email..
            // luckily, we can automatically recover from this.
            $inputs = getDOMDocumentFormInputs ( $domd, true, false ) ['challenge'];
            assert ( array_key_exists ( 'email', $inputs ) );
            $inputs ['email'] = $recoveryEmailChallengeAnswer;
            $url = $authChallenge->getAttribute ( "action" );
            if (! parse_url ( $url, PHP_URL_HOST )) {
                $url = 'https://' . parse_url ( $hc->getinfo ( CURLINFO_EFFECTIVE_URL ), PHP_URL_HOST ) . $url;
            }
            $html = $hc->setopt_array ( array (
                    CURLOPT_POST => 1,
                    CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
                    CURLOPT_URL => $url 
            ) )->exec ()->getStdOut ();
            $domd = @DOMDocument::loadHTML ( $html );
            $xp = new DOMXPath ( $domd );
            // TODO: detect incorrect recovery email supplied error here.
        }
    }
    unset ( $authChallenge );

    if (! empty ( $loginErrorText )) {
        throw new \RuntimeException ( 'errors loggin in: ' . $loginErrorText );
    } else {
        // logged in! :D
    }
    if ($requestHtmlVersion) {
        // now we need to enable HTML view, it's a <form> POST request, but we can't use getDOMDocumentFormInputs (bug?)
        $found = false;
        foreach ( $domd->getElementsByTagName ( "form" ) as $form ) {
            if (false === stripos ( $form->textContent, "Gmail's basic HTML view, which doesn't require JavaScript" ) && $xp->query ( "./input[@value='Load basic HTML']", $form )->length === 0) {
                continue;
            }
            $found = true;
            $url = $form->getAttribute ( "action" );
            if (! parse_url ( $url, PHP_URL_HOST )) {
                $url = $hc->getinfo ( CURLINFO_EFFECTIVE_URL ) . $url;
            }
            // hhb_var_dump ( $url ) & die ();
            $inputs = [ ];
            foreach ( $form->getElementsByTagName ( "input" ) as $input ) {
                $name = $input->getAttribute ( "name" );
                if (empty ( $name )) {
                    continue;
                }
                $inputs [$name] = $input->getAttribute ( "value" );
            }
            // hhb_var_dump ( $inputs ) & die ();
            break;
        }
        if (! $found) {
            $str = 'failed to find HTML version request form!';
            // hhb_var_dump ( $str, $hc->getStdErr (), $hc->getStdOut (), $inputs ); // & die ();
            throw new \RuntimeException ( $str );
        }
        $html = $hc->setopt_array ( array (
                CURLOPT_POST => 1,
                CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
                CURLOPT_URL => $url 
        ) )->exec ()->getStdOut ();
    }
    hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ); // & die ();
    return $hc;
}
function rightTrim($str, $needle, $caseSensitive = true) {
    $strPosFunction = $caseSensitive ? "strpos" : "stripos";
    if ($strPosFunction ( $str, $needle, strlen ( $str ) - strlen ( $needle ) ) !== false) {
        $str = substr ( $str, 0, - strlen ( $needle ) );
    }
    return $str;
}
function getDOMDocumentFormInputs(\DOMDocument $domd, bool $getOnlyFirstMatches = false, bool $getElements = true): array {
    // :DOMNodeList?
    if (! $getOnlyFirstMatches && ! $getElements) {
        throw new \InvalidArgumentException ( '!$getElements is currently only implemented for $getOnlyFirstMatches (cus im lazy and nobody has written the code yet)' );
    }
    $forms = $domd->getElementsByTagName ( 'form' );
    $parsedForms = array ();
    $isDescendantOf = function (\DOMNode $decendant, \DOMNode $ele): bool {
        $parent = $decendant;
        while ( NULL !== ($parent = $parent->parentNode) ) {
            if ($parent === $ele) {
                return true;
            }
        }
        return false;
    };
    // i can't use array_merge on DOMNodeLists :(
    $merged = function () use (&$domd): array {
        $ret = array ();
        foreach ( $domd->getElementsByTagName ( "input" ) as $input ) {
            $ret [] = $input;
        }
        foreach ( $domd->getElementsByTagName ( "textarea" ) as $textarea ) {
            $ret [] = $textarea;
        }
        foreach ( $domd->getElementsByTagName ( "button" ) as $button ) {
            $ret [] = $button;
        }
        return $ret;
    };
    $merged = $merged ();
    foreach ( $forms as $form ) {
        $inputs = function () use (&$domd, &$form, &$isDescendantOf, &$merged): array {
            $ret = array ();
            foreach ( $merged as $input ) {
                // hhb_var_dump ( $input->getAttribute ( "name" ), $input->getAttribute ( "id" ) );
                if ($input->hasAttribute ( "disabled" )) {
                    // ignore disabled elements?
                    continue;
                }
                $name = $input->getAttribute ( "name" );
                if ($name === '') {
                    // echo "inputs with no name are ignored when submitted by mainstream browsers (presumably because of specs)... follow suite?", PHP_EOL;
                    continue;
                }
                if (! $isDescendantOf ( $input, $form ) && $form->getAttribute ( "id" ) !== '' && $input->getAttribute ( "form" ) !== $form->getAttribute ( "id" )) {
                    // echo "this input does not belong to this form.", PHP_EOL;
                    continue;
                }
                if (! array_key_exists ( $name, $ret )) {
                    $ret [$name] = array (
                            $input 
                    );
                } else {
                    $ret [$name] [] = $input;
                }
            }
            return $ret;
        };
        $inputs = $inputs (); // sorry about that, Eclipse gets unstable on IIFE syntax.
        $hasName = true;
        $name = $form->getAttribute ( "id" );
        if ($name === '') {
            $name = $form->getAttribute ( "name" );
            if ($name === '') {
                $hasName = false;
            }
        }
        if (! $hasName) {
            $parsedForms [] = array (
                    $inputs 
            );
        } else {
            if (! array_key_exists ( $name, $parsedForms )) {
                $parsedForms [$name] = array (
                        $inputs 
                );
            } else {
                $parsedForms [$name] [] = $tmp;
            }
        }
    }
    unset ( $form, $tmp, $hasName, $name, $i, $input );
    if ($getOnlyFirstMatches) {
        foreach ( $parsedForms as $key => $val ) {
            $parsedForms [$key] = $val [0];
        }
        unset ( $key, $val );
        foreach ( $parsedForms as $key1 => $val1 ) {
            foreach ( $val1 as $key2 => $val2 ) {
                $parsedForms [$key1] [$key2] = $val2 [0];
            }
        }
    }
    if ($getElements) {
        return $parsedForms;
    }
    $ret = array ();
    foreach ( $parsedForms as $formName => $arr ) {
        $ret [$formName] = array ();
        foreach ( $arr as $ele ) {
            $ret [$formName] [$ele->getAttribute ( "name" )] = $ele->getAttribute ( "value" );
        }
    }
    return $ret;
}
...