$connection['installation_id'], 'x-fammro-timestamp' => $timestamp, 'x-fammro-nonce' => $nonce, 'x-fammro-signature' => base64_encode( $signature ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- Signature transport format. 'x-fammro-plugin-version' => FAMMRO_VERSION, ) ); } /** * Public key in SPKI (DER) form, base64 encoded, as FAMMRO expects it. * * @param string $public_key Raw 32 byte Ed25519 public key. */ public static function spki( string $public_key ): string { return base64_encode( hex2bin( '302a300506032b6570032100' ) . $public_key ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- Key transport format. } /** * Perform the request. * * @param string $method HTTP method. * @param string $path Path below the API base. * @param string $raw Raw body. * @param array $headers Extra headers. * @return array{status: int, body: array}|null */ private static function request( string $method, string $path, string $raw, array $headers ): ?array { $base = self::base(); if ( '' === $base || ! str_starts_with( $path, '/' ) ) { return null; } $args = array( 'method' => $method, 'timeout' => self::TIMEOUT, 'redirection' => 0, 'headers' => array_merge( array( 'Accept' => 'application/json', 'Content-Type' => 'application/json', ), $headers ), 'user-agent' => 'FAMMRO-WordPress/' . FAMMRO_VERSION . '; ' . home_url( '/' ), ); if ( '' !== $raw ) { $args['body'] = $raw; } $response = wp_remote_request( $base . $path, $args ); if ( is_wp_error( $response ) ) { return null; } $decoded = json_decode( (string) wp_remote_retrieve_body( $response ), true ); return array( 'status' => (int) wp_remote_retrieve_response_code( $response ), 'body' => is_array( $decoded ) ? $decoded : array(), ); } /** * JSON exactly as the API re-serialises it for the signature (no escaped slashes or unicode). * * @param array $body Body. */ private static function encode( array $body ): string { $json = wp_json_encode( empty( $body ) ? new \stdClass() : $body, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); return false === $json ? '{}' : $json; } /** * Query part of a path including the question mark. * * @param string $path Path. */ private static function query( string $path ): string { $position = strpos( $path, '?' ); return false === $position ? '' : substr( $path, $position ); } /** * HTTPS base URL or empty string. * * @param string $url Configured URL. */ private static function https_base( string $url ): string { $url = untrailingslashit( trim( $url ) ); return str_starts_with( $url, 'https://' ) && false !== wp_parse_url( $url ) ? $url : ''; } }