$master_user = $user_id;
$options = compact( 'user_tokens', 'master_user' );
} else {
$options = compact( 'user_tokens' );
}
return Jetpack_Options::update_options( $options );
}
/**
* Sign a user role with the master access token.
* If not specified, will default to the current user.
*
* @access public
*
* @param string $role User role.
* @param int $user_id ID of the user.
* @return string Signed user role.
*/
public function sign_role( $role, $user_id = null ) {
if ( empty( $user_id ) ) {
$user_id = (int) get_current_user_id();
}
if ( ! $user_id ) {
return false;
}
$token = $this->get_access_token();
if ( ! $token || is_wp_error( $token ) ) {
return false;
}
return $role . ':' . hash_hmac( 'md5', "{$role}|{$user_id}", $token->secret );
}
/**
* Increases the request timeout value to 30 seconds.
*
* @return int Returns 30.
*/
public function return_30() {
return 30;
}
/**
* Gets the requested token.
*
* Tokens are one of two types:
* 1. Blog Tokens: These are the "main" tokens. Each site typically has one Blog Token,
* though some sites can have multiple "Special" Blog Tokens (see below). These tokens
* are not associated with a user account. They represent the site's connection with
* the Jetpack servers.
* 2. User Tokens: These are "sub-"tokens. Each connected user account has one User Token.
*
* All tokens look like "{$token_key}.{$private}". $token_key is a public ID for the
* token, and $private is a secret that should never be displayed anywhere or sent
* over the network; it's used only for signing things.
*
* Blog Tokens can be "Normal" or "Special".
* * Normal: The result of a normal connection flow. They look like
* "{$random_string_1}.{$random_string_2}"
* That is, $token_key and $private are both random strings.
* Sites only have one Normal Blog Token. Normal Tokens are found in either
* Jetpack_Options::get_option( 'blog_token' ) (usual) or the JETPACK_BLOG_TOKEN
* constant (rare).
* * Special: A connection token for sites that have gone through an alternative
* connection flow. They look like:
* ";{$special_id}{$special_version};{$wpcom_blog_id};.{$random_string}"
* That is, $private is a random string and $token_key has a special structure with
* lots of semicolons.
* Most sites have zero Special Blog Tokens. Special tokens are only found in the
* JETPACK_BLOG_TOKEN constant.
*
* In particular, note that Normal Blog Tokens never start with ";" and that
* Special Blog Tokens always do.
*
* When searching for a matching Blog Tokens, Blog Tokens are examined in the following
* order:
* 1. Defined Special Blog Tokens (via the JETPACK_BLOG_TOKEN constant)
* 2. Stored Normal Tokens (via Jetpack_Options::get_option( 'blog_token' ))
* 3. Defined Normal Tokens (via the JETPACK_BLOG_TOKEN constant)
*
* @param int|false $user_id false: Return the Blog Token. int: Return that user's User Token.
* @param string|false $token_key If provided, check that the token matches the provided input.
* @param bool|true $suppress_errors If true, return a falsy value when the token isn't found; When false, return a descriptive WP_Error when the token isn't found.
*
* @return object|false|WP_Error
*/
public function get_access_token( $user_id = false, $token_key = false, $suppress_errors = true ) {
if ( $this->is_locked() ) {
$this->delete_all();
return false;
}
$possible_special_tokens = array();
$possible_normal_tokens = array();
$user_tokens = $this->get_user_tokens();
if ( $user_id ) {
if ( ! $user_tokens ) {
return $suppress_errors ? false : new WP_Error( 'no_user_tokens', __( 'No user tokens found', 'jetpack-connection' ) );
}
if ( true === $user_id ) { // connection owner.
$user_id = Jetpack_Options::get_option( 'master_user' );
if ( ! $user_id ) {
return $suppress_errors ? false : new WP_Error( 'empty_master_user_option', __( 'No primary user defined', 'jetpack-connection' ) );
}
}
if ( ! isset( $user_tokens[ $user_id ] ) || ! $user_tokens[ $user_id ] ) {
// translators: %s is the user ID.
return $suppress_errors ? false : new WP_Error( 'no_token_for_user', sprintf( __( 'No token for user %d', 'jetpack-connection' ), $user_id ) );
}
$user_token_chunks = explode( '.', $user_tokens[ $user_id ] );
if ( empty( $user_token_chunks[1] ) || empty( $user_token_chunks[2] ) ) {
// translators: %s is the user ID.
return $suppress_errors ? false : new WP_Error( 'token_malformed', sprintf( __( 'Token for user %d is malformed', 'jetpack-connection' ), $user_id ) );
}
if ( $user_token_chunks[2] !== (string) $user_id ) {
// translators: %1$d is the ID of the requested user. %2$d is the user ID found in the token.
return $suppress_errors ? false : new WP_Error( 'user_id_mismatch', sprintf( __( 'Requesting user_id %1$d does not match token user_id %2$d', 'jetpack-connection' ), $user_id, $user_token_chunks[2] ) );
}
$possible_normal_tokens[] = "{$user_token_chunks[0]}.{$user_token_chunks[1]}";
} else {
$stored_blog_token = Jetpack_Options::get_option( 'blog_token' );
if ( $stored_blog_token ) {
$possible_normal_tokens[] = $stored_blog_token;
}
$defined_tokens_string = Constants::get_constant( 'JETPACK_BLOG_TOKEN' );
if ( $defined_tokens_string ) {
$defined_tokens = explode( ',', $defined_tokens_string );
foreach ( $defined_tokens as $defined_token ) {
if ( ';' === $defined_token[0] ) {
$possible_special_tokens[] = $defined_token;
} else {
$possible_normal_tokens[] = $defined_token;
}
}
}
}
if ( self::MAGIC_NORMAL_TOKEN_KEY === $token_key ) {
$possible_tokens = $possible_normal_tokens;
} else {
$possible_tokens = array_merge( $possible_special_tokens, $possible_normal_tokens );
}
if ( ! $possible_tokens ) {
// If no user tokens were found, it would have failed earlier, so this is about blog token.
return $suppress_errors ? false : new WP_Error( 'no_possible_tokens', __( 'No blog token found', 'jetpack-connection' ) );
}
$valid_token = false;
if ( false === $token_key ) {
// Use first token.
$valid_token = $possible_tokens[0];
} elseif ( self::MAGIC_NORMAL_TOKEN_KEY === $token_key ) {
// Use first normal token.
$valid_token = $possible_tokens[0]; // $possible_tokens only contains normal tokens because of earlier check.
} else {
// Use the token matching $token_key or false if none.
// Ensure we check the full key.
$token_check = rtrim( $token_key, '.' ) . '.';
foreach ( $possible_tokens as $possible_token ) {
if ( hash_equals( substr( $possible_token, 0, strlen( $token_check ) ), $token_check ) ) {
$valid_token = $possible_token;
break;
}
}
}
if ( ! $valid_token ) {
if ( $user_id ) {
// translators: %d is the user ID.
return $suppress_errors ? false : new WP_Error( 'no_valid_user_token', sprintf( __( 'Invalid token for user %d', 'jetpack-connection' ), $user_id ) );
} else {
return $suppress_errors ? false : new WP_Error( 'no_valid_blog_token', __( 'Invalid blog token', 'jetpack-connection' ) );
}
}
return (object) array(
'secret' => $valid_token,
'external_user_id' => (int) $user_id,
);
}
/**
* Updates the blog token to a new value.
*
* @access public
*
* @param string $token the new blog token value.
* @return Boolean Whether updating the blog token was successful.
*/
public function update_blog_token( $token ) {
return Jetpack_Options::update_option( 'blog_token', $token );
}
/**
* Unlinks the current user from the linked WordPress.com user.
*
* @access public
* @static
*
* @todo Refactor to properly load the XMLRPC client independently.
*
* @param int $user_id The user identifier.
*
* @return bool Whether the disconnection of the user was successful.
*/
public function disconnect_user( $user_id ) {
$tokens = $this->get_user_tokens();
if ( ! $tokens ) {
return false;
}
if ( ! isset( $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;
}
}
Fatal error: Uncaught Error: Class 'Automattic\Jetpack\Connection\Tokens' not found in /var/www/html/cronicasdorock.com.br/web/wp-content/plugins/jetpack/jetpack_vendor/automattic/jetpack-connection/src/class-manager.php:612
Stack trace:
#0 /var/www/html/cronicasdorock.com.br/web/wp-content/plugins/jetpack/jetpack_vendor/automattic/jetpack-connection/src/class-manager.php(645): Automattic\Jetpack\Connection\Manager->get_tokens()
#1 /var/www/html/cronicasdorock.com.br/web/wp-content/plugins/jetpack/class.jetpack.php(1492): Automattic\Jetpack\Connection\Manager->is_connected()
#2 /var/www/html/cronicasdorock.com.br/web/wp-content/plugins/jetpack/class.jetpack.php(814): Jetpack::is_connection_ready()
#3 /var/www/html/cronicasdorock.com.br/web/wp-includes/class-wp-hook.php(324): Jetpack->configure('')
#4 /var/www/html/cronicasdorock.com.br/web/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters('', Array)
#5 /var/www/html/cronicasdorock.com.br/web/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
#6 /var/www/html/ in /var/www/html/cronicasdorock.com.br/web/wp-content/plugins/jetpack/jetpack_vendor/automattic/jetpack-connection/src/class-manager.php on line 612