$tokens[ $user_id ] ) ) { return false; } unset( $tokens[ $user_id ] ); $this->update_user_tokens( $tokens ); return true; } /** * Returns an array of user_id's that have user tokens for communicating with wpcom. * Able to select by specific capability. * * @deprecated 1.30.0 * @see Manager::get_connected_users * * @param string $capability The capability of the user. * @param int|null $limit How many connected users to get before returning. * @return array Array of WP_User objects if found. */ public function get_connected_users( $capability = 'any', $limit = null ) { _deprecated_function( __METHOD__, '1.30.0' ); return ( new Manager( 'jetpack' ) )->get_connected_users( $capability, $limit ); } /** * Fetches a signed token. * * @param object $token the token. * @return WP_Error|string a signed token */ public function get_signed_token( $token ) { if ( ! isset( $token->secret ) || empty( $token->secret ) ) { return new WP_Error( 'invalid_token' ); } list( $token_key, $token_secret ) = explode( '.', $token->secret ); $token_key = sprintf( '%s:%d:%d', $token_key, Constants::get_constant( 'JETPACK__API_VERSION' ), $token->external_user_id ); $timestamp = time(); if ( function_exists( 'wp_generate_password' ) ) { $nonce = wp_generate_password( 10, false ); } else { $nonce = substr( sha1( wp_rand( 0, 1000000 ) ), 0, 10 ); } $normalized_request_string = implode( "\n", array( $token_key, $timestamp, $nonce, ) ) . "\n"; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode $signature = base64_encode( hash_hmac( 'sha1', $normalized_request_string, $token_secret, true ) ); $auth = array( 'token' => $token_key, 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signature, ); $header_pieces = array(); foreach ( $auth as $key => $value ) { $header_pieces[] = sprintf( '%s="%s"', $key, $value ); } return implode( ' ', $header_pieces ); } /** * Gets the list of user tokens * * @since 1.30.0 * * @return bool|array An array of user tokens where keys are user IDs and values are the tokens. False if no user token is found. */ public function get_user_tokens() { return Jetpack_Options::get_option( 'user_tokens' ); } /** * Updates the option that stores the user tokens * * @since 1.30.0 * * @param array $tokens An array of user tokens where keys are user IDs and values are the tokens. * @return bool Was the option successfully updated? * * @todo add validate the input. */ public function update_user_tokens( $tokens ) { return Jetpack_Options::update_option( 'user_tokens', $tokens ); } /** * Lock the tokens to the current site URL. * * @param int $timespan How long the tokens should be locked, in seconds. * * @return bool */ public function set_lock( $timespan = HOUR_IN_SECONDS ) { try { $expires = ( new DateTime() )->add( DateInterval::createFromDateString( (int) $timespan . ' seconds' ) ); } catch ( Exception $e ) { return false; } if ( false === $expires ) { return false; } // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode return Jetpack_Options::update_option( 'token_lock', $expires->format( static::DATE_FORMAT_ATOM ) . '|||' . base64_encode( Urls::site_url() ) ); } /** * Remove the site lock from tokens. * * @return bool */ public function remove_lock() { Jetpack_Options::delete_option( 'token_lock' ); return true; } /** * Check if the domain is locked, remove the lock if needed. * Possible scenarios: * - lock expired, site URL matches the lock URL: remove the lock, return false. * - lock not expired, site URL matches the lock URL: return false. * - site URL does not match the lock URL (expiration date is ignored): return true, do not remove the lock. * * @return bool */ public function is_locked() { $the_lock = Jetpack_Options::get_option( 'token_lock' ); if ( ! $the_lock ) { // Not locked. return false; } $the_lock = explode( '|||', $the_lock, 2 ); if ( count( $the_lock ) !== 2 ) { // Something's wrong with the lock. $this->remove_lock(); return false; } // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode $locked_site_url = base64_decode( $the_lock[1] ); $expires = $the_lock[0]; $expiration_date = DateTime::createFromFormat( static::DATE_FORMAT_ATOM, $expires ); if ( false === $expiration_date || ! $locked_site_url ) { // Something's wrong with the lock. $this->remove_lock(); return false; } if ( Urls::site_url() === $locked_site_url ) { if ( new DateTime() > $expiration_date ) { // Site lock expired. // Site URL matches, removing the lock. $this->remove_lock(); } return false; } // Site URL doesn't match. return true; } }