ID ); return true; } /** * Get the authorization header. * * On certain systems and configurations, the Authorization header will be * stripped out by the server or PHP. Typically this is then used to * generate `PHP_AUTH_USER`/`PHP_AUTH_PASS` but not passed on. We use * `getallheaders` here to try and grab it out instead. * * @since 3.7.0 * @return string Authorization header if set. */ protected static function get_authorization_header() { if ( ! empty( $_SERVER['HTTP_AUTHORIZATION'] ) ) { return wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized } if ( function_exists( 'getallheaders' ) ) { $headers = getallheaders(); // Check for the authorization header case-insensitively. foreach ( $headers as $key => $value ) { if ( 'authorization' === strtolower( $key ) ) { return $value; } } } return ''; } /** * Check if this is a request to WCCOM Site REST API. * * Before WordPress parses the request only the URL path is checked. Requests carrying `rest_route` * return false until then, and `authentication_fallback()` authenticates them once the route is resolved. * * @since 3.7.0 * @return bool */ protected static function is_request_to_wccom_site_rest_api() { global $wp; // Once WordPress is dispatching REST, the route it resolved is the one that counts. if ( wp_is_rest_endpoint() ) { $route = $wp instanceof WP ? ( $wp->query_vars['rest_route'] ?? null ) : null; return is_string( $route ) && str_starts_with( ltrim( $route, '/' ), 'wccom-site/' ); } // Before that, a rest_route in the query or body can override the path, so leave those requests to authentication_fallback(). if ( isset( $_REQUEST['rest_route'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return false; } $path = wp_parse_url( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ), PHP_URL_PATH ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Only compared against the REST prefix. return is_string( $path ) && str_contains( $path, trailingslashit( rest_get_url_prefix() ) . 'wccom-site/' ); } /** * Verify WooCommerce.com request from a given body and signature request. * * @since 3.7.0 * @param string $body Request body. * @param string $signature Request signature found in X-Woo-Signature header. * @param string $access_token_secret Access token secret for this site. * @return bool */ protected static function verify_wccom_request( $body, $signature, $access_token_secret ) { // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $data = array( 'host' => $_SERVER['HTTP_HOST'], 'request_uri' => urldecode( remove_query_arg( array( 'token', 'signature' ), $_SERVER['REQUEST_URI'] ) ), 'method' => strtoupper( $_SERVER['REQUEST_METHOD'] ), ); // phpcs:enable if ( ! empty( $body ) ) { $data['body'] = $body; } $expected_signature = hash_hmac( 'sha256', wp_json_encode( $data ), $access_token_secret ); return hash_equals( $expected_signature, $signature ); } /** * Register wccom-site REST namespace. * * @since 3.7.0 * @param array $namespaces List of registered namespaces. * @return array Registered namespaces. */ public static function register_rest_namespace( $namespaces ) { require_once WC_ABSPATH . 'includes/wccom-site/rest-api/class-wc-rest-wccom-site-installer-error-codes.php'; require_once WC_ABSPATH . 'includes/wccom-site/rest-api/class-wc-rest-wccom-site-installer-error.php'; require_once WC_ABSPATH . 'includes/wccom-site/rest-api/endpoints/abstract-wc-rest-wccom-site-controller.php'; require_once WC_ABSPATH . 'includes/wccom-site/rest-api/endpoints/class-wc-rest-wccom-site-installer-controller.php'; require_once WC_ABSPATH . 'includes/wccom-site/rest-api/endpoints/class-wc-rest-wccom-site-ssr-controller.php'; require_once WC_ABSPATH . 'includes/wccom-site/rest-api/endpoints/class-wc-rest-wccom-site-status-controller.php'; require_once WC_ABSPATH . 'includes/wccom-site/rest-api/endpoints/class-wc-rest-wccom-site-connection-controller.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/class-wc-wccom-site-installation-state.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/class-wc-wccom-site-installation-state-storage.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/class-wc-wccom-site-installation-manager.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/installation-steps/interface-installaton-step.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/installation-steps/class-wc-wccom-site-installation-step-get-product-info.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/installation-steps/class-wc-wccom-site-installation-step-download-product.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/installation-steps/class-wc-wccom-site-installation-step-unpack-product.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/installation-steps/class-wc-wccom-site-installation-step-move-product.php'; require_once WC_ABSPATH . 'includes/wccom-site/installation/installation-steps/class-wc-wccom-site-installation-step-activate-product.php'; $namespaces['wccom-site/v2'] = array( 'installer' => 'WC_REST_WCCOM_Site_Installer_Controller', 'ssr' => 'WC_REST_WCCOM_Site_SSR_Controller', 'status' => 'WC_REST_WCCOM_Site_Status_Controller', 'connection' => 'WC_REST_WCCOM_Site_Connection_Controller', ); return $namespaces; } } WC_WCCOM_Site::load();