e( 'keyring-request' ), 'nonce' => wp_create_nonce( "keyring-request-$service_name" ), 'publicize_action' => 1, ), admin_url() ); }/** * Build contents handling Keyring connection management into Sharing settings screen. */ public static function intercept_request() { if ( ! empty( $_GET['publicize_action'] ) && isset( $_GET['action'] ) ) { $service_name = null;if ( isset( $_GET['service'] ) ) { $service_name = filter_var( wp_unslash( $_GET['service'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We verify below. }switch ( $_GET['action'] ) {case 'request': check_admin_referer( 'keyring-request', 'kr_nonce' ); check_admin_referer( "keyring-request-$service_name", 'nonce' );$verification = ( new Secrets() )->generate( 'publicize' ); if ( ! $verification ) { $url = ( new Paths() )->admin_url( 'page=jetpack#/settings' ); wp_die( sprintf( wp_kses( /* Translators: placeholder is a URL to a Settings page. */ __( "Jetpack is not connected. Please connect Jetpack by visiting Settings.", 'jetpack-publicize-pkg' ), array( 'a' => array( 'href' => array(), ), ) ), esc_url( $url ) ) );} $stats_options = get_option( 'stats_options' ); $wpcom_blog_id = Jetpack_Options::get_option( 'id' ); $wpcom_blog_id = ! empty( $wpcom_blog_id ) ? $wpcom_blog_id : $stats_options['blog_id'];$for = isset( $_GET['for'] ) ? sanitize_text_field( wp_unslash( $_GET['for'] ) ) : 'publicize';$custom_inputs = array();// For Bluesky. if ( isset( $_GET['handle'] ) && isset( $_GET['app_password'] ) ) { $custom_inputs['handle'] = sanitize_text_field( wp_unslash( $_GET['handle'] ) );$custom_inputs['app_password'] = sanitize_text_field( wp_unslash( $_GET['app_password'] ) ); }// For Mastodon. if ( isset( $_GET['instance'] ) ) { $custom_inputs['instance'] = sanitize_text_field( wp_unslash( $_GET['instance'] ) ); }$user = wp_get_current_user(); $redirect = self::api_url( $service_name, urlencode_deep( $custom_inputs + array( 'action' => 'request', 'redirect_uri' => add_query_arg( array( 'action' => 'done' ), menu_page_url( 'sharing', false ) ), 'for' => $for, // required flag that says this connection is intended for publicize. 'siteurl' => site_url(), 'state' => $user->ID, 'blog_id' => $wpcom_blog_id, 'secret_1' => $verification['secret_1'], 'secret_2' => $verification['secret_2'], 'eol' => $verification['exp'], ) ) ); wp_redirect( $redirect ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- The API URL is an external URL and is filterable. exit( 0 );case 'completed': /* * We do not use a nonce here, * since we're populating a local cache of * the Publicize connections that were created and stored on WordPress.com. */ $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.fetchPublicizeConnections' );if ( ! $xml->isError() ) { $response = $xml->getResponse(); Jetpack_Options::update_option( 'publicize_connections', $response ); }break;case 'delete': $id = isset( $_GET['id'] ) ? filter_var( wp_unslash( $_GET['id'] ) ) : null;check_admin_referer( 'keyring-request', 'kr_nonce' ); check_admin_referer( "keyring-request-$service_name", 'nonce' );self::disconnect( $service_name, $id );do_action( 'connection_disconnected', $service_name ); break; } } }/** * Remove a Publicize connection * * @param string $service_name Service name. * @param string $connection_id Connection ID. * @param int|bool $_blog_id Blog ID. * @param int|bool $_user_id User ID. * @param bool $force_delete Force delete the connection. */ public static function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.deletePublicizeConnection', $connection_id );if ( ! $xml->isError() ) { Jetpack_Options::update_option( 'publicize_connections', $xml->getResponse() ); } else { return false; } } }